library(ggplot2)
library(grid)
library(forestploter)
library(tidyverse)
saveto <- "/Volumes/Research Project/IAT_Retest/Plotting/SavedFigs/"
path <- "/Volumes/"
setwd(paste0(path,"Research Project/IAT_Retest/Estimates/UCR/"))
Warning: The working directory was changed to /Volumes/Research Project/IAT_Retest/Estimates/UCR inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
Cal1 <-read.csv("IndividualParametersQuadUCR1.csv", header = T)
Cal2 <-read.csv("IndividualParametersQuadUCR2.csv", header = T)

colnames(Cal1)[2:ncol(Cal1)]<-paste(colnames(Cal1[2:ncol(Cal1)]),"T1",sep="_")
colnames(Cal2)[2:ncol(Cal2)]<-paste(colnames(Cal2[2:ncol(Cal2)]),"T2",sep="_")

Q.Cal <- merge(Cal1, Cal2, by = "subject", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/PI/"))
PI1 <- read.csv("IndividualParametersQuadProjectImplicit1.csv")
PI2 <- read.csv("IndividualParametersQuadProjectImplicit2.csv")

colnames(PI1)[2:ncol(PI1)]<-paste(colnames(PI1[2:ncol(PI1)]),"T1",sep="_")
colnames(PI2)[2:ncol(PI2)]<-paste(colnames(PI2[2:ncol(PI2)]),"T2",sep="_")

Q.PI <- merge(PI1, PI2, by = "ID", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Gawronski/"))
Gaw1 <- read.csv("IndividualParametersQuadGawronski1.csv")
Gaw2 <- read.csv("IndividualParametersQuadGawronski2.csv")

colnames(Gaw1)[2:ncol(Gaw1)]<-paste(colnames(Gaw1[2:ncol(Gaw1)]),"T1",sep="_")
colnames(Gaw2)[2:ncol(Gaw2)]<-paste(colnames(Gaw2[2:ncol(Gaw2)]),"T2",sep="_")

Q.Gaw <- merge(Gaw1, Gaw2, by = "code", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Forscher/"))
For1<-read.csv("IndividualParametersQuadForscher1.csv", header = T)
For2<-read.csv("IndividualParametersQuadForscher2.csv", header = T)

colnames(For1)[2:ncol(For1)]<-paste(colnames(For1[2:ncol(For1)]),"T1",sep="_")
colnames(For2)[2:ncol(For2)]<-paste(colnames(For2[2:ncol(For2)]),"T2",sep="_")

Q.For <- merge(For1, For2, by = "subject", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai1/"))
Lai11<-read.csv("IndividualParametersLaiStudy1Quad1.csv", header = T)
Lai12<-read.csv("IndividualParametersLaiStudy1Quad2.csv", header = T)

colnames(Lai11)[2:ncol(Lai11)]<-paste(colnames(Lai11[2:ncol(Lai11)]),"T1",sep="_")
colnames(Lai12)[2:ncol(Lai12)]<-paste(colnames(Lai12[2:ncol(Lai12)]),"T2",sep="_")

Q.Lai1 <- merge(Lai11, Lai12, by = "session_id", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai2/"))
Lai21<-read.csv("IndividualParametersLaiStudy2Quad1.csv", header = T)
Lai22<-read.csv("IndividualParametersLaiStudy2Quad2.csv", header = T)

colnames(Lai21)[2:ncol(Lai21)]<-paste(colnames(Lai21[2:ncol(Lai21)]),"T1",sep="_")
colnames(Lai22)[2:ncol(Lai22)]<-paste(colnames(Lai22[2:ncol(Lai22)]),"T2",sep="_")

Q.Lai2 <- merge(Lai21, Lai22, by = "session_id", all.x = T, all.y = T)

colnames(Q.Cal)[1] <- "subID"
Q.Cal <- cbind(Q.Cal, Study = "Calanchini")
colnames(Q.PI)[1] <- "subID"
Q.PI <- cbind(Q.PI, Study = "PI")
colnames(Q.Gaw)[1] <- "subID"
Q.Gaw <- cbind(Q.Gaw, Study = "Gawronski")
colnames(Q.For)[1] <- "subID"
Q.For <- cbind(Q.For, Study = "Forscher")
colnames(Q.Lai1)[1] <- "subID"
Q.Lai1 <- cbind(Q.Lai1, Study = "Lai 1")
colnames(Q.Lai2)[1] <- "subID"
Q.Lai2 <- cbind(Q.Lai2, Study = "Lai 2")

Quad <- rbind(Q.Cal,Q.PI,Q.Gaw,Q.For,Q.Lai1,Q.Lai2)


Quad$Study[Quad$Study=="PI"]<-"Project Implicit, 2020"
Quad$Study[Quad$Study=="Calanchini"]<-"Wilson & Calanchini, 2022"
Quad$Study[Quad$Study=="Lai 1"]<-"Lai et al., 2016 (Study 1)  "
Quad$Study[Quad$Study=="Lai 2"]<-"Lai et al., 2016 (Study 2)  "
Quad$Study[Quad$Study=="Gawronski"]<-"Gawronski et al., 2017"
Quad$Study[Quad$Study=="Forscher"]<-"Forscher et al., 2017"
path <- "/Volumes/"
setwd(paste0(path,"Research Project/IAT_Retest/Estimates/UCR/"))
Warning: The working directory was changed to /Volumes/Research Project/IAT_Retest/Estimates/UCR inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
Cal1 <-read.csv("IndividualParametersPDUCR1.csv", header = T)
Cal2 <-read.csv("IndividualParametersPDUCR2.csv", header = T)

colnames(Cal1)[2:ncol(Cal1)]<-paste(colnames(Cal1[2:ncol(Cal1)]),"T1",sep="_")
colnames(Cal2)[2:ncol(Cal2)]<-paste(colnames(Cal2[2:ncol(Cal2)]),"T2",sep="_")

P.Cal <- merge(Cal1, Cal2, by = "subject", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/PI/"))
PI1 <- read.csv("IndividualParametersProjectImplicitPD1.csv")
PI2 <- read.csv("IndividualParametersProjectImplicitPD2.csv")

colnames(PI1)[2:ncol(PI1)]<-paste(colnames(PI1[2:ncol(PI1)]),"T1",sep="_")
colnames(PI2)[2:ncol(PI2)]<-paste(colnames(PI2[2:ncol(PI2)]),"T2",sep="_")

P.PI <- merge(PI1, PI2, by = "ID", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Gawronski/"))
Gaw1 <- read.csv("IndividualParametersPDGawronski1.csv")
Gaw2 <- read.csv("IndividualParametersPDGawronski2.csv")

colnames(Gaw1)[2:ncol(Gaw1)]<-paste(colnames(Gaw1[2:ncol(Gaw1)]),"T1",sep="_")
colnames(Gaw2)[2:ncol(Gaw2)]<-paste(colnames(Gaw2[2:ncol(Gaw2)]),"T2",sep="_")

P.Gaw <- merge(Gaw1, Gaw2, by = "code", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Forscher/"))
For1<-read.csv("IndividualParametersForscherPD1.csv", header = T)
For2<-read.csv("IndividualParametersForscherPD2.csv", header = T)

colnames(For1)[2:ncol(For1)]<-paste(colnames(For1[2:ncol(For1)]),"T1",sep="_")
colnames(For2)[2:ncol(For2)]<-paste(colnames(For2[2:ncol(For2)]),"T2",sep="_")

P.For <- merge(For1, For2, by = "subject", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai1/"))
Lai11<-read.csv("IndividualParametersLaiStudy1PD1.csv", header = T)
Lai12<-read.csv("IndividualParametersLaiStudy1PD2.csv", header = T)

colnames(Lai11)[2:ncol(Lai11)]<-paste(colnames(Lai11[2:ncol(Lai11)]),"T1",sep="_")
colnames(Lai12)[2:ncol(Lai12)]<-paste(colnames(Lai12[2:ncol(Lai12)]),"T2",sep="_")

P.Lai1 <- merge(Lai11, Lai12, by = "session_id", all.x = T, all.y = T)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai2/"))
Lai21<-read.csv("IndividualParametersLaiStudy2PD1.csv", header = T)
Lai22<-read.csv("IndividualParametersLaiStudy2PD2.csv", header = T)

colnames(Lai21)[2:ncol(Lai21)]<-paste(colnames(Lai21[2:ncol(Lai21)]),"T1",sep="_")
colnames(Lai22)[2:ncol(Lai22)]<-paste(colnames(Lai22[2:ncol(Lai22)]),"T2",sep="_")

P.Lai2 <- merge(Lai21, Lai22, by = "session_id", all.x = T, all.y = T)

colnames(P.Cal)[1] <- "subID"
P.Cal <- cbind(P.Cal, Study = "Calanchini")
colnames(P.PI)[1] <- "subID"
P.PI <- cbind(P.PI, Study = "PI")
colnames(P.Gaw)[1] <- "subID"
P.Gaw <- cbind(P.Gaw, Study = "Gawronski")
colnames(P.For)[1] <- "subID"
P.For <- cbind(P.For, Study = "Forscher")
colnames(P.Lai1)[1] <- "subID"
P.Lai1 <- cbind(P.Lai1, Study = "Lai 1")
colnames(P.Lai2)[1] <- "subID"
P.Lai2 <- cbind(P.Lai2, Study = "Lai 2")

PD <- rbind(P.Cal,P.PI,P.Gaw,P.For,P.Lai1,P.Lai2)

PD$Study[PD$Study=="PI"]<-"Project Implicit, 2020"
PD$Study[PD$Study=="Calanchini"]<-"Wilson & Calanchini, 2022"
PD$Study[PD$Study=="Lai 1"]<-"Lai et al., 2016 (Study 1)  "
PD$Study[PD$Study=="Lai 2"]<-"Lai et al., 2016 (Study 2)  "
PD$Study[PD$Study=="Gawronski"]<-"Gawronski et al., 2017"
PD$Study[PD$Study=="Forscher"]<-"Forscher et al., 2017"

Quad Model

Associate Black-Bad

ACbbScatter <- ggplot(Quad, aes(x=ACbb1_T1, y=ACbb1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1) + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Association Black-Bad",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa() 
ACbbScatter
ggsave(paste0(saveto,"ACbbScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"ACbbScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Associate White-Good

ACwgScatter <- ggplot(Quad, aes(x=ACwg1_T1, y=ACwg1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Association White-Good",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) + theme(legend.title = element_text(size = 9)) +
  jtools::theme_apa()
ACwgScatter
ggsave(paste0(saveto,"ACwgScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"ACwgScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Detection

DScatter <- ggplot(Quad, aes(x=D1_T1, y=D1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Detection",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) + theme(legend.title = element_text(size = 9)) +
  jtools::theme_apa()
DScatter
ggsave(paste0(saveto,"DScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"DScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Overcoming Bias

OBScatter <- ggplot(Quad, aes(x=OB1_T1, y=OB1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Overcoming Bias",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) + theme(legend.title = element_text(size = 9))  +
  jtools::theme_apa()
OBScatter
ggsave(paste0(saveto,"OBScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"OBScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Guessing

GScatter <- ggplot(Quad, aes(x=G1_T1, y=G1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Guessing",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
ggsave(paste0(saveto,"GScatter.jpg"),dpi=600)
Saving 7 x 7 in image
ggsave(paste0(saveto,"GScatter.tiff"),dpi=600)

Panel

library(ggpubr)
QuadPanel1 <- ggarrange(ACwgScatter, ACbbScatter, DScatter, OBScatter, GScatter,
          ncol = 3, nrow = 2, common.legend = T)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
QuadPanel1


require(grid)   # for the textGrob() function

QuadPanel2 <- ggarrange(ACwgScatter  + theme(plot.title = element_text(size=12)) + theme(legend.text = element_text(size = 8)) + rremove("ylab") + rremove("xlab"), 
                        ACbbScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        DScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        OBScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        GScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
          ncol = 3, nrow = 2, common.legend = T, labels = NULL, legend = "bottom",
          align = "hv", 
                    font.label = list(size = 10, color = "black", face = "bold", family = NULL, position = "top"))
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
QuadPanel2


annotate_figure(QuadPanel2, left = textGrob("Time 2", rot = 90, vjust = 1, hjust = 0, gp = gpar(cex = 1)),
                    bottom = textGrob("Time 1", vjust = -6.5, gp = gpar(cex = 1))) + theme(legend.position = c(0,-1))
ggsave(paste0(saveto,"QuadPanel.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"QuadPanel.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

PD Model

Automatic Black

AbScatter <- ggplot(PD, aes(x=Ab1_T1, y=Ab1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Automatic Black",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
AbScatter
ggsave(paste0(saveto,"AbScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"AbScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Associate White

AwScatter <- ggplot(PD, aes(x=Aw1_T1, y=Aw1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Automatic White",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
AwScatter
ggsave(paste0(saveto,"AwScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"AwScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control Good

CpScatter <- ggplot(PD, aes(x=Cp1_T1, y=Cp1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control Good",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CpScatter
ggsave(paste0(saveto,"CpScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CpScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control Bad

CuScatter <- ggplot(PD, aes(x=Cu1_T1, y=Cu1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control Bad",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CuScatter
ggsave(paste0(saveto,"CuScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CuScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control White

CwScatter <- ggplot(PD, aes(x=Cw1_T1, y=Cw1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control White",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CwScatter
ggsave(paste0(saveto,"CwScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CwScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control Black

CbScatter <- ggplot(PD, aes(x=Cb1_T1, y=Cb1_T2, color=Study)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control Black",
       x="Time 1", y = "Time 2") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CbScatter
ggsave(paste0(saveto,"CbScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CbScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Panel

library(ggpubr)
PDPanel1 <- ggarrange(AwScatter, AbScatter, CuScatter, CpScatter, CbScatter, CwScatter,
          ncol = 3, nrow = 2, common.legend = T)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
PDPanel1


require(grid)   # for the textGrob() function

PDPanel2 <- ggarrange(AwScatter  + theme(plot.title = element_text(size=12))  + theme(legend.text = element_text(size = 8)) + rremove("ylab") + rremove("xlab"), 
                        AbScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CuScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CpScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CbScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CwScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
          ncol = 3, nrow = 2, common.legend = T, labels = NULL, legend = "bottom",
          align = "hv", 
                    font.label = list(size = 10, color = "black", face = "bold", family = NULL, position = "top"))
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
PDPanel2 <- annotate_figure(PDPanel2, left = textGrob("Time 2", rot = 90, vjust = 1, hjust = 0, gp = gpar(cex = 1)),
                    bottom = textGrob("Time 1", vjust = -6.5, gp = gpar(cex = 1))) + theme(legend.position = c(0,-1))
PDPanel2
ggsave(paste0(saveto,"PDPanel.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"PDPanel.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Reliability Meta-Analysis

dt <- read.csv("~/Documents/GitHub/MPT-Reliability/Retest/output/combQuad_Df.csv")[2:6]

dt$Param[dt$Param=="D"]<-"Detection"
dt$Param[dt$Param=="OB"]<-"Overcoming Bias"
dt$Param[dt$Param=="ACbb"]<-"Association Black-Bad"
dt$Param[dt$Param=="ACwg"]<-"Association White-Good"
dt$Param[dt$Param=="G"]<-"Guessing"

dt$Param[dt$Param=="PI"]<-"Project Implicit, 2020"
dt$Param[dt$Param=="Calanchini"]<-"Wilson & Calanchini, 2022"
dt$Param[dt$Param=="Lai1"]<-"Lai et al., 2016 (Study 1)  "
dt$Param[dt$Param=="Lai2"]<-"Lai et al., 2016 (Study 2)  "
dt$Param[dt$Param=="Gawronski"]<-"Gawronski et al., 2017"
dt$Param[dt$Param=="Forscher"]<-"Forscher et al., 2017"

# indent the subgroup if there is a number in the placebo column
dt$Param <- ifelse(dt$type==0, 
                      dt$Param,
                      paste0(" ", dt$Param))

colnames(dt)[colnames(dt)=="Param"] <- "   "
dt$` ` <- paste(rep(" ", 20), collapse = " ")
dt$`ICC (95% CI)` <- ifelse(is.na(dt$ICC), "",
                             sprintf("%.2f [%.2f, %.2f]",
                                     dt$ICC, dt$CI.LB, dt$CI.UB))


dt$ICCstudy <- ifelse(dt$type==1, dt$ICC, NA)
dt$ICC.LBstudy <- ifelse(dt$type==1, dt$CI.LB, NA)
dt$ICC.UBstudy <- ifelse(dt$type==1, dt$CI.UB, NA)
dt$Sizestudy <- ifelse(dt$type==1, .6, NA)
dt$Sizemeta <- ifelse(dt$type==0, 1.2, NA)
dt$ICCmeta <- ifelse(dt$type==0, dt$ICC, NA)
dt$ICC.LBmeta <- ifelse(dt$type==0, dt$CI.LB, NA)
dt$ICC.UBmeta <- ifelse(dt$type==0, dt$CI.UB, NA)

#dt<-dt[c(1:4,6:7)]
dt<-dt[c(1:4,6:ncol(dt))]
colnames(dt)[colnames(dt)=="ICC (95% CI)"] <- "     "

library(forestploter)
# p <- forest(
#   dt[c(1,5,6)],
#             est = dt$ICC,
#             lower = dt$CI.LB, 
#             upper = dt$CI.UB,
#             ci_column = 2,
#             ref_line = .4,
#             xlim = c(-.1, 1),
#             ticks_at = c(0, .4,.6, .75, 1),
#   sizes = .1
# )

tm <- forest_theme(
                   ci_pch = c(15, 16),
                   ci_col = c("black","red"),
                   ci_lty = c( "solid", "dashed"),
                  # footnote_col = "blue",
                   legend_name = " ",
                  legend_position = "bottom",
                   legend_value = c("Meta-Analysis ", "Study")
                  
                  )

p <- forest(
  dt[c(1,5,6)],
            est = list(dt$ICCmeta, dt$ICCstudy),
            lower = list(dt$ICC.LBmeta, dt$ICC.LBstudy), 
            upper = list(dt$ICC.UBmeta, dt$ICC.UBstudy),
              ci_column = 2,
            ref_line = .4,
            xlim = c(-.1, 1),
            ticks_at = c(0, .4,.6, .75, 1),
  sizes = list(dt$Sizemeta, dt$Sizestudy),
  theme = tm
)

library(grid)
p <- edit_plot(p,
               row = seq(from=1,to=nrow(dt),by=7),
               gp = gpar(fontface = c("bold","italic")
                         ), col = 1)

studyInds <- setdiff(1:nrow(dt),seq(from=1,to=nrow(dt),by=7))
paramInds <- seq(from=1,to=nrow(dt),by=7)

p <- edit_plot(p, row = studyInds, which = "background",
               gp = gpar(fill = "white"))
p <- edit_plot(p, row = paramInds, which = "background",
               gp = gpar(fill = "grey"))
png(paste0(saveto,"Quad_TRT.png"), units="in", width=10, height=12, res=300)
plot(p)
dev.off()
null device 
          1 
# ggsave function
ggplot2::ggsave(paste0(saveto,"Quad_TRT.png"),
                dpi = 300,
                width = 6, height = 11, units = "in", plot=p)

ggplot2::ggsave(paste0(saveto,"Quad_TRT.tiff"),
                dpi = 600,
                width = 6, height = 11, units = "in", plot=p)
dt <- read.csv("~/Documents/GitHub/MPT-Reliability/Retest/output/combPD_Df.csv")[2:6]

dt$Param[dt$Param=="Ab"]<-"Automatic Black"
dt$Param[dt$Param=="Aw"]<-"Automatic White"
dt$Param[dt$Param=="Cb"]<-"Control Black"
dt$Param[dt$Param=="Cw"]<-"Control White"
dt$Param[dt$Param=="Cu"]<-"Control Bad"
dt$Param[dt$Param=="Cp"]<-"Control Good"

dt$Param[dt$Param=="PI"]<-"Project Implicit, 2020"
dt$Param[dt$Param=="Calanchini"]<-"Wilson & Calanchini, 2022"
dt$Param[dt$Param=="Lai1"]<-"Lai et al., 2016 (Study 1)  "
dt$Param[dt$Param=="Lai2"]<-"Lai et al., 2016 (Study 2)  "
dt$Param[dt$Param=="Gawronski"]<-"Gawronski et al., 2017"
dt$Param[dt$Param=="Forscher"]<-"Forscher et al., 2017"

# indent the subgroup if there is a number in the placebo column
dt$Param <- ifelse(dt$type==0, 
                      dt$Param,
                      paste0(" ", dt$Param))

colnames(dt)[colnames(dt)=="Param"] <- "   "
colnames(dt)[colnames(dt)=="Param"] <- "   "
dt$` ` <- paste(rep(" ", 20), collapse = " ")
dt$`ICC (95% CI)` <- ifelse(is.na(dt$ICC), "",
                             sprintf("%.2f [%.2f, %.2f]",
                                     dt$ICC, dt$CI.LB, dt$CI.UB))

dt$ICCstudy <- ifelse(dt$type==1, dt$ICC, NA)
dt$ICC.LBstudy <- ifelse(dt$type==1, dt$CI.LB, NA)
dt$ICC.UBstudy <- ifelse(dt$type==1, dt$CI.UB, NA)
dt$Sizestudy <- ifelse(dt$type==1, .6, NA)
dt$Sizemeta <- ifelse(dt$type==0, 1.2, NA)
dt$ICCmeta <- ifelse(dt$type==0, dt$ICC, NA)
dt$ICC.LBmeta <- ifelse(dt$type==0, dt$CI.LB, NA)
dt$ICC.UBmeta <- ifelse(dt$type==0, dt$CI.UB, NA)

#dt<-dt[c(1:4,6:7)]
dt<-dt[c(1:4,6:ncol(dt))]
colnames(dt)[colnames(dt)=="ICC (95% CI)"] <- "     "

library(forestploter)
# p <- forest(
#   dt[c(1,5,6)],
#             est = dt$ICC,
#             lower = dt$CI.LB, 
#             upper = dt$CI.UB,
#             ci_column = 2,
#             ref_line = .4,
#             xlim = c(-.1, 1),
#             ticks_at = c(0, .4,.6, .75, 1),
#   sizes = .1
# )

tm <- forest_theme(
                   ci_pch = c(15, 16),
                   ci_col = c("black","red"),
                   ci_lty = c( "solid", "dashed"),
                  # footnote_col = "blue",
                   legend_name = " ",
                  legend_position = "bottom",
                   legend_value = c("Meta-Analysis ", "Study")
                  
                  )

p <- forest(
  dt[c(1,5,6)],
            est = list(dt$ICCmeta, dt$ICCstudy),
            lower = list(dt$ICC.LBmeta, dt$ICC.LBstudy), 
            upper = list(dt$ICC.UBmeta, dt$ICC.UBstudy),
              ci_column = 2,
            ref_line = .4,
            xlim = c(-.1, 1),
            ticks_at = c(0, .4,.6, .75, 1),
  sizes = list(dt$Sizemeta, dt$Sizestudy),
  theme = tm
)

library(grid)
p <- edit_plot(p,
               row = seq(from=1,to=nrow(dt),by=7),
               gp = gpar(fontface = c("bold","italic")
                         ), col = 1)

studyInds <- setdiff(1:nrow(dt),seq(from=1,to=nrow(dt),by=7))
paramInds <- seq(from=1,to=nrow(dt),by=7)

p <- edit_plot(p, row = studyInds, which = "background",
               gp = gpar(fill = "white"))
p <- edit_plot(p, row = paramInds, which = "background",
               gp = gpar(fill = "grey"))
png(paste0(saveto,"PDP_TRT.png"), units="in", width=10, height=15, res=300)
plot(p)
dev.off()
null device 
          1 
# ggsave function
ggplot2::ggsave(paste0(saveto,"PDP_TRT.png"),
                dpi = 300,
                width = 6, height = 13, units = "in", plot=p)

ggplot2::ggsave(paste0(saveto,"PDP_TRT.tiff"),
                dpi = 600,
                width = 6, height = 13, units = "in", plot=p)

Recovery

setwd(paste0("/Volumes/Research Project/IAT_Retest/Recovery/RecoveredParams/PD/"))
Warning: The working directory was changed to /Volumes/Research Project/IAT_Retest/Recovery/RecoveredParams/PD inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
times<-c("Time1","Time2")

allrecovs <- as.data.frame(matrix(ncol=14,nrow=0))

PDdirs <- list.dirs(path = ".", full.names = TRUE, recursive = TRUE)[-1]
for(d in PDdirs){
  for(ti in times){
    curFiles <- list.files(path=d,pattern="\\.csv$")
    id<-grep(ti,curFiles)
    output<-read.csv(paste0(d,"/",curFiles[id]))
    name<-gsub("./","",d)
    name<-gsub(" ","",name)
    
    if(ti=="Time1"){
      #colnames(output) <- paste(colnames(output),"T1",sep="_")
      output$time <- "T1"
    }else if(ti=="Time2"){
      #colnames(output) <- paste(colnames(output),"T2",sep="_")
      output$time <- "T2"
    }
    
    assign(paste0(name,".PD.Recov.",ti),output)
  }
  df <- rbind(get(paste0(name,".PD.Recov.Time1")),get(paste0(name,".PD.Recov.Time2")))
  assign(paste0(name,".PD.Recov"),df)
  allrecovs <- rbind(allrecovs,cbind(df,Study=name))
}


allrecovs$Study <- gsub("Lai1", "Lai 1", allrecovs$Study)
allrecovs$Study <- gsub("Lai2", "Lai 2", allrecovs$Study)
PD.recovs <- allrecovs
PD.recovs <- dplyr::rename(PD.recovs, subID=X)

tapply(PD.recovs$Ab1, PD.recovs$Study, function(x) length(x))
Calanchini   Forscher  Gawronski      Lai 1      Lai 2         PI 
       210         64        232        160        926       2480 
path <- "/Volumes/"
setwd(paste0(path,"Research Project/IAT_Retest/Estimates/UCR/"))
Warning: The working directory was changed to /Volumes/Research Project/IAT_Retest/Estimates/UCR inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
Cal1 <-read.csv("IndividualParametersPDUCR1.csv", header = T)
Cal2 <-read.csv("IndividualParametersPDUCR2.csv", header = T)

Cal1$time <- "T1"
Cal2$time <- "T2"
Cal1$subID <- 1:nrow(Cal1)
Cal2$subID <- 1:nrow(Cal2)
P.Cal <- rbind(Cal1, Cal2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/PI/"))
PI1 <- read.csv("IndividualParametersProjectImplicitPD1.csv")
PI2 <- read.csv("IndividualParametersProjectImplicitPD2.csv")

PI1$time <- "T1"
PI2$time <- "T2"
PI1$subID <- 1:nrow(PI1)
PI2$subID <- 1:nrow(PI2)
P.PI <- rbind(PI1, PI2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Gawronski/"))
Gaw1 <- read.csv("IndividualParametersPDGawronski1.csv")
Gaw2 <- read.csv("IndividualParametersPDGawronski2.csv")

Gaw1$time <- "T1"
Gaw2$time <- "T2"
Gaw1$subID <- 1:nrow(Gaw1)
Gaw2$subID <- 1:nrow(Gaw2)
P.Gaw <- rbind(Gaw1, Gaw2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Forscher/"))
For1<-read.csv("IndividualParametersForscherPD1.csv", header = T)
For2<-read.csv("IndividualParametersForscherPD2.csv", header = T)

For1$time <- "T1"
For2$time <- "T2"
For1$subID <- 1:nrow(For1)
For2$subID <- 1:nrow(For2)
P.For <- rbind(For1, For2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai1/"))
Lai11<-read.csv("IndividualParametersLaiStudy1PD1.csv", header = T)
Lai12<-read.csv("IndividualParametersLaiStudy1PD2.csv", header = T)

Lai11$time <- "T1"
Lai12$time <- "T2"
Lai11$subID <- 1:nrow(Lai11)
Lai12$subID <- 1:nrow(Lai12)
P.Lai1 <- rbind(Lai11, Lai12)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai2/"))
Lai21<-read.csv("IndividualParametersLaiStudy2PD1.csv", header = T)
Lai22<-read.csv("IndividualParametersLaiStudy2PD2.csv", header = T)

Lai21$time <- "T1"
Lai22$time <- "T2"
Lai21$subID <- 1:nrow(Lai21)
Lai22$subID <- 1:nrow(Lai22)
P.Lai2 <- rbind(Lai21,Lai22)

colnames(P.Cal)[1] <- "subID"
P.Cal <- cbind(P.Cal, Study = "Calanchini")
colnames(P.PI)[1] <- "subID"
P.PI <- cbind(P.PI, Study = "PI")
colnames(P.Gaw)[1] <- "subID"
P.Gaw <- cbind(P.Gaw, Study = "Gawronski")
colnames(P.For)[1] <- "subID"
P.For <- cbind(P.For, Study = "Forscher")
colnames(P.Lai1)[1] <- "subID"
P.Lai1 <- cbind(P.Lai1, Study = "Lai 1")
colnames(P.Lai2)[1] <- "subID"
P.Lai2 <- cbind(P.Lai2, Study = "Lai 2")

PD.orig <- rbind(P.Cal,P.PI,P.Gaw,P.For,P.Lai1,P.Lai2)
PD.orig[1] <- NULL

colnames(PD.recovs)[2: (ncol(PD.recovs)-2) ] <- paste(colnames(PD.recovs)[2: (ncol(PD.recovs)-2) ],"R",sep="_")
colnames(PD.orig)[1: (ncol(PD.orig)-3) ] <- paste(colnames(PD.orig)[1: (ncol(PD.orig)-3) ],"O",sep="_")
PD.orig <- PD.orig[order(PD.orig$Study, PD.orig$time),]
PD.recovs <- PD.recovs[order(PD.recovs$Study, PD.recovs$time),]

#PD.orig.recovs <- cbind(PD.orig,PD.recovs)
PD.orig.recovs <- merge(PD.orig, PD.recovs, by = c("subID","Study","time"))

PD.orig.recovs$Study[PD.orig.recovs$Study=="PI"]<-"Project Implicit, 2020"
PD.orig.recovs$Study[PD.orig.recovs$Study=="Calanchini"]<-"Wilson & Calanchini, 2022"
PD.orig.recovs$Study[PD.orig.recovs$Study=="Lai 1"]<-"Lai et al., 2016 (Study 1)  "
PD.orig.recovs$Study[PD.orig.recovs$Study=="Lai 2"]<-"Lai et al., 2016 (Study 2)  "
PD.orig.recovs$Study[PD.orig.recovs$Study=="Gawronski"]<-"Gawronski et al., 2017"
PD.orig.recovs$Study[PD.orig.recovs$Study=="Forscher"]<-"Forscher et al., 2017"

Recovery

PD Model

Automatic Black

AbScatter <- ggplot(PD.orig.recovs, aes(x=Ab1_O, y=Ab1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Automatic Black",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()

AbScatter
ggsave(paste0(saveto,"AbScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"AbScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Automatic White

AwScatter <- ggplot(PD.orig.recovs, aes(x=Aw1_O, y=Aw1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)   + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Automatic White",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
AwScatter
ggsave(paste0(saveto,"AwScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"AwScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control Good

CpScatter <- ggplot(PD.orig.recovs, aes(x=Cp1_O, y=Cp1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)   + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control Good",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CpScatter
ggsave(paste0(saveto,"CpScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"AwScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control Bad

CuScatter <- ggplot(PD.orig.recovs, aes(x=Cu1_O, y=Cu1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)   + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control Bad",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CuScatter
ggsave(paste0(saveto,"CuScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CuScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control White

CwScatter <- ggplot(PD.orig.recovs, aes(x=Cw1_O, y=Cw1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control White",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CwScatter
ggsave(paste0(saveto,"CwScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CwScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Control Black

CbScatter <- ggplot(PD.orig.recovs, aes(x=Cb1_O, y=Cb1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Control Black",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
CbScatter
ggsave(paste0(saveto,"CbScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"CbScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Panel

library(ggpubr)
PDPanel1 <- ggarrange(AwScatter, AbScatter, CuScatter, CpScatter, CbScatter, CwScatter,
          ncol = 3, nrow = 2, common.legend = T)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
PDPanel1


require(grid)   # for the textGrob() function

PDPanel2 <- ggarrange(AwScatter  + theme(plot.title = element_text(size=12)) + theme(legend.text = element_text(size = 8)) + rremove("ylab") + rremove("xlab"), 
                        AbScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CuScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CpScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CbScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        CwScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
          ncol = 3, nrow = 2, common.legend = T, labels = NULL, legend = c("bottom"),
          align = "hv", 
                    font.label = list(size = 10, color = "black", face = "bold", family = NULL, position = "top"))
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
PDPanel2 <- annotate_figure(PDPanel2, left = textGrob("Recovered", rot = 90, vjust = 1, hjust = 0, gp = gpar(cex = 1)),
                    bottom = textGrob("Original", vjust = -6.5, gp = gpar(cex = 1))) + theme(legend.position = c(0,-1))
PDPanel2
ggsave(paste0(saveto,"PDPanelREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"PDPanelREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Quad Model

Recovery

setwd(paste0("/Volumes/Research Project/IAT_Retest/Recovery/RecoveredParams/Quad/"))
Warning: The working directory was changed to /Volumes/Research Project/IAT_Retest/Recovery/RecoveredParams/Quad inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
times<-c("Time1","Time2")

allrecovs <- as.data.frame(matrix(ncol=14,nrow=0))

Quaddirs <- list.dirs(path = ".", full.names = TRUE, recursive = TRUE)[-1]
for(d in Quaddirs){
  for(ti in times){
    curFiles <- list.files(path=d,pattern="\\.csv$")
    id<-grep(ti,curFiles)
    output<-read.csv(paste0(d,"/",curFiles[id]))
    name<-gsub("./","",d)
    name<-gsub(" ","",name)
    
    if(ti=="Time1"){
      #colnames(output) <- paste(colnames(output),"T1",sep="_")
      output$time <- "T1"
    }else if(ti=="Time2"){
      #colnames(output) <- paste(colnames(output),"T2",sep="_")
      output$time <- "T2"
    }
    
    assign(paste0(name,".Quad.Recov.",ti),output)
  }
  df <- rbind(get(paste0(name,".Quad.Recov.Time1")),get(paste0(name,".Quad.Recov.Time2")))
  assign(paste0(name,".Quad.Recov"),df)
  allrecovs <- rbind(allrecovs,cbind(df,Study=name))
}


allrecovs$Study <- gsub("Lai1", "Lai 1", allrecovs$Study)
allrecovs$Study <- gsub("Lai2", "Lai 2", allrecovs$Study)
Quad.recovs <- allrecovs
Quad.recovs <- dplyr::rename(Quad.recovs, subID=X)

tapply(Quad.recovs$ACbb1, Quad.recovs$Study, function(x) length(x))
Calanchini   Forscher  Gawronski      Lai 1      Lai 2         PI 
       210         64        232        160        926       2480 
path <- "/Volumes/"
setwd(paste0(path,"Research Project/IAT_Retest/Estimates/UCR/"))
Warning: The working directory was changed to /Volumes/Research Project/IAT_Retest/Estimates/UCR inside a notebook chunk. The working directory will be reset when the chunk is finished running. Use the knitr root.dir option in the setup chunk to change the working directory for notebook chunks.
Cal1 <-read.csv("IndividualParametersQuadUCR1.csv", header = T)
Cal2 <-read.csv("IndividualParametersQuadUCR2.csv", header = T)

Cal1$time <- "T1"
Cal2$time <- "T2"
Cal1$subID <- 1:nrow(Cal1)
Cal2$subID <- 1:nrow(Cal2)
P.Cal <- rbind(Cal1, Cal2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/PI/"))
PI1 <- read.csv("IndividualParametersQuadProjectImplicit1.csv")
PI2 <- read.csv("IndividualParametersQuadProjectImplicit2.csv")

PI1$time <- "T1"
PI2$time <- "T2"
PI1$subID <- 1:nrow(PI1)
PI2$subID <- 1:nrow(PI2)
P.PI <- rbind(PI1, PI2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Gawronski/"))
Gaw1 <- read.csv("IndividualParametersQuadGawronski1.csv")
Gaw2 <- read.csv("IndividualParametersQuadGawronski2.csv")

Gaw1$time <- "T1"
Gaw2$time <- "T2"
Gaw1$subID <- 1:nrow(Gaw1)
Gaw2$subID <- 1:nrow(Gaw2)
P.Gaw <- rbind(Gaw1, Gaw2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Forscher/"))
For1<-read.csv("IndividualParametersQuadForscher1.csv", header = T)
For2<-read.csv("IndividualParametersQuadForscher2.csv", header = T)

For1$time <- "T1"
For2$time <- "T2"
For1$subID <- 1:nrow(For1)
For2$subID <- 1:nrow(For2)
P.For <- rbind(For1, For2)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai1/"))
Lai11<-read.csv("IndividualParametersLaiStudy1Quad1.csv", header = T)
Lai12<-read.csv("IndividualParametersLaiStudy1Quad2.csv", header = T)

Lai11$time <- "T1"
Lai12$time <- "T2"
Lai11$subID <- 1:nrow(Lai11)
Lai12$subID <- 1:nrow(Lai12)
P.Lai1 <- rbind(Lai11, Lai12)

setwd(paste0(path,"Research Project/IAT_Retest/Estimates/Lai2/"))
Lai21<-read.csv("IndividualParametersLaiStudy2Quad1.csv", header = T)
Lai22<-read.csv("IndividualParametersLaiStudy2Quad2.csv", header = T)

Lai21$time <- "T1"
Lai22$time <- "T2"
Lai21$subID <- 1:nrow(Lai21)
Lai22$subID <- 1:nrow(Lai22)
P.Lai2 <- rbind(Lai21,Lai22)

colnames(P.Cal)[1] <- "subID"
P.Cal <- cbind(P.Cal, Study = "Calanchini")
colnames(P.PI)[1] <- "subID"
P.PI <- cbind(P.PI, Study = "PI")
colnames(P.Gaw)[1] <- "subID"
P.Gaw <- cbind(P.Gaw, Study = "Gawronski")
colnames(P.For)[1] <- "subID"
P.For <- cbind(P.For, Study = "Forscher")
colnames(P.Lai1)[1] <- "subID"
P.Lai1 <- cbind(P.Lai1, Study = "Lai 1")
colnames(P.Lai2)[1] <- "subID"
P.Lai2 <- cbind(P.Lai2, Study = "Lai 2")

Quad.orig <- rbind(P.Cal,P.PI,P.Gaw,P.For,P.Lai1,P.Lai2)
Quad.orig[1] <- NULL
colnames(Quad.recovs)[2: (ncol(Quad.recovs)-2) ] <- paste(colnames(Quad.recovs)[2: (ncol(Quad.recovs)-2) ],"R",sep="_")
colnames(Quad.orig)[1: (ncol(Quad.orig)-3) ] <- paste(colnames(Quad.orig)[1: (ncol(Quad.orig)-3) ],"O",sep="_")
Quad.orig <- Quad.orig[order(Quad.orig$Study, Quad.orig$time),]
Quad.recovs <- Quad.recovs[order(Quad.recovs$Study, Quad.recovs$time),]

#Quad.orig.recovs <- cbind(Quad.orig,Quad.recovs)
Quad.orig.recovs <- merge(Quad.orig, Quad.recovs, by = c("subID","Study","time"))

Quad.orig.recovs$Study[Quad.orig.recovs$Study=="PI"]<-"Project Implicit, 2020"
Quad.orig.recovs$Study[Quad.orig.recovs$Study=="Calanchini"]<-"Wilson & Calanchini, 2022"
Quad.orig.recovs$Study[Quad.orig.recovs$Study=="Lai 1"]<-"Lai et al., 2016 (Study 1)  "
Quad.orig.recovs$Study[Quad.orig.recovs$Study=="Lai 2"]<-"Lai et al., 2016 (Study 2)  "
Quad.orig.recovs$Study[Quad.orig.recovs$Study=="Gawronski"]<-"Gawronski et al., 2017"
Quad.orig.recovs$Study[Quad.orig.recovs$Study=="Forscher"]<-"Forscher et al., 2017"

Quad Model

Associate Black-Bad

ACbbScatter <- ggplot(Quad.orig.recovs, aes(x=ACbb1_O, y=ACbb1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Association Black-Bad",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
ACbbScatter
ggsave(paste0(saveto,"ACbbScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"ACbbScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Associate White-Good

ACwgScatter <- ggplot(Quad.orig.recovs, aes(x=ACwg1_O, y=ACwg1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Association White-Good",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
ACwgScatter
ggsave(paste0(saveto,"ACwgScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"ACwgScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Detection

DScatter <- ggplot(Quad.orig.recovs, aes(x=D1_O, y=D1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Detection",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
DScatter
ggsave(paste0(saveto,"DScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"DScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Overcoming Bias

OBScatter <- ggplot(Quad.orig.recovs, aes(x=OB1_O, y=OB1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Overcoming Bias",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
OBScatter
ggsave(paste0(saveto,"OBScatterREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"OBScatterREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Guessing

GScatter <- ggplot(Quad.orig.recovs, aes(x=G1_O, y=G1_R, color=Study, shape=time)) + 
  geom_point(alpha = .2)+
  geom_smooth(method=lm, se=TRUE,
             color="darkgrey",alpha=1)  + geom_abline(intercept = 0, slope = 1) + ylim(0,1) + xlim(0,1) + labs(title="Guessing",
       x="Original", y = "Recovered") + guides(colour = guide_legend(override.aes = list(alpha = 1))) +
  jtools::theme_apa()
GScatter
ggsave(paste0(saveto,"GScatter.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"GScatter.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Panel

library(ggpubr)
QuadPanel1 <- ggarrange(ACwgScatter, ACbbScatter, DScatter, OBScatter, GScatter,
          ncol = 3, nrow = 2, common.legend = T)
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
QuadPanel1


require(grid)   # for the textGrob() function

QuadPanel2 <- ggarrange(ACwgScatter  + theme(plot.title = element_text(size=12))  + theme(legend.text = element_text(size = 8)) + rremove("ylab") + rremove("xlab"), 
                        ACbbScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        DScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        OBScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
                        GScatter  + theme(plot.title = element_text(size=12)) + rremove("ylab") + rremove("xlab"),
          ncol = 3, nrow = 2, common.legend = T, labels = NULL, legend = "bottom",
          align = "hv", 
                    font.label = list(size = 10, color = "black", face = "bold", family = NULL, position = "top"))
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
`geom_smooth()` using formula 'y ~ x'
QuadPanel2


annotate_figure(QuadPanel2, left = textGrob("Recovered", rot = 90, vjust = 1, hjust = 0, gp = gpar(cex = 1)),
                    bottom = textGrob("Original", vjust = -6.5, gp = gpar(cex = 1))) + theme(legend.position = c(0,-1))
ggsave(paste0(saveto,"QuadPanelREC.jpg"),dpi=600)
Saving 7.29 x 4.51 in image
ggsave(paste0(saveto,"QuadPanelREC.tiff"),dpi=600)
Saving 7.29 x 4.51 in image

Recovery Meta-Analysis

Quad

dt <- read.csv("~/Documents/GitHub/MPT-Reliability/Recovery/output/combQuad_Recovery_Df.csv")[2:7]
dt$id <- unlist(lapply(1:5, function(x) rep(x,times=13)))

dt$Param[dt$Param=="D"]<-"Detection"
dt$Param[dt$Param=="OB"]<-"Overcoming Bias"
dt$Param[dt$Param=="ACbb"]<-"Association Black-Bad"
dt$Param[dt$Param=="ACwg"]<-"Association White-Good"
dt$Param[dt$Param=="G"]<-"Guessing"

dt$Param[dt$Param=="PI"]<-"Project Implicit, 2020"
dt$Param[dt$Param=="Calanchini"]<-"Wilson & Calanchini, 2022"
dt$Param[dt$Param=="Lai1"]<-"Lai et al., 2016 (Study 1)  "
dt$Param[dt$Param=="Lai2"]<-"Lai et al., 2016 (Study 2)  "
dt$Param[dt$Param=="Gawronski"]<-"Gawronski et al., 2017"
dt$Param[dt$Param=="Forscher"]<-"Forscher et al., 2017"

# indent the subgroup if there is a number in the placebo column
dt$Param <- ifelse(dt$type==0, 
                      dt$Param,
                      paste0(" ", dt$Param))

dt$` ` <- paste(rep(" ", 20), collapse = " ")
dt$`Recovery (95% CI)` <- ifelse(is.na(dt$Recov), "",
                             sprintf("%.2f [%.2f, %.2f]",
                                     dt$Recov, dt$CI.LB, dt$CI.UB))

dt2 <- pivot_wider(dt, id_cols = c("Param","id"),  names_from = c(Time), values_from = c(Recov,CI.LB,CI.UB,`Recovery (95% CI)`) )
dt2$`Recovery [95% CI]` <- ifelse(!is.na(dt2$`Recovery (95% CI)_Meta`), paste0("                 ",dt2$`Recovery (95% CI)_Meta`), paste0("T1 :", paste0(dt2$`Recovery (95% CI)_Time1`), " ; ", "T2: ", paste0(dt2$`Recovery (95% CI)_Time2`)))
dt2$` ` <- paste(rep(" ", 20), collapse = " ")


dt3<-dt2 %>% select(Param,Recov_Meta:11,15,16)

colnames(dt3)[colnames(dt3)=="Param"] <- "   "
colnames(dt3)[colnames(dt3)=="Recovery [95% CI]"] <- "    "

dt3$size_Meta <- ifelse(is.na(dt3$Recov_Meta), NA, 1.2)
dt3$size_T1 <- ifelse(is.na(dt3$Recov_Time1), NA, .6)
dt3$size_T2 <- ifelse(is.na(dt3$Recov_Time2), NA, .6)

# Set-up theme
tm <- forest_theme(
                   ci_pch = c(15, 16, 17),
                   ci_col = c("black","red","blue"),
                   ci_lty = c( "solid", "dashed", "dotted"),
                  # footnote_col = "blue",
                   legend_name = " ",
                  legend_position = "bottom",
                   legend_value = c("Meta-Analysis ", "Time 1 ", "Time 2 "))

library(forestploter)
p <- forest(
  dt3[c(1,12,11)],
            est = list(dt3$Recov_Meta, dt3$Recov_Time1, dt3$Recov_Time2),
            lower = list(dt3$CI.LB_Meta, dt3$CI.LB_Time1, dt3$CI.LB_Time2), 
            upper = list(dt3$CI.UB_Meta, dt3$CI.UB_Time1, dt3$CI.UB_Time2),
            ci_column = 2,
            ref_line = .7,
            xlim = c(-.1, 1),
            ticks_at = c(0, .2, .5, .7, 1),
  sizes = list(dt3$size_Meta, dt3$size_T1, dt3$size_T2),
  theme = tm
)
plot(p)


library(grid)
p <- edit_plot(p,
               row = seq(from=1,to=nrow(dt3),by=7),
               gp = gpar(fontface = c("bold","italic")
                         ), col = 1)

studyInds <- setdiff(1:nrow(dt3),seq(from=1,to=nrow(dt3),by=7))
paramInds <- seq(from=1,to=nrow(dt),by=7)

p <- edit_plot(p, row = studyInds, which = "background",
               gp = gpar(fill = "white"))
p <- edit_plot(p, row = paramInds, which = "background",
               gp = gpar(fill = "grey"))
png("~/Desktop/Quad_RecovForest.png", units="in", width=10, height=15, res=300)
plot(p)
dev.off()
null device 
          1 
# ggsave function
ggplot2::ggsave(paste0(saveto,"Quad_RecovForest.png"),
                dpi = 300,
                width = 8, height = 15, units = "in", plot=p)

ggplot2::ggsave(paste0(saveto,"Quad_RecovForest.tiff"),
                dpi = 300,
                width = 8, height = 15, units = "in", plot=p)
dt <- read.csv("~/Documents/GitHub/MPT-Reliability/Recovery/output/combPD_Recovery_Df.csv")[2:7]
dt$id <- unlist(lapply(1:6, function(x) rep(x,times=13)))

dt$Param[dt$Param=="Ab"]<-"Automatic Black"
dt$Param[dt$Param=="Aw"]<-"Automatic White"
dt$Param[dt$Param=="Cb"]<-"Control Black"
dt$Param[dt$Param=="Cw"]<-"Control White"
dt$Param[dt$Param=="Cu"]<-"Control Bad"
dt$Param[dt$Param=="Cp"]<-"Control Good"

dt$Param[dt$Param=="PI"]<-"Project Implicit, 2020"
dt$Param[dt$Param=="Calanchini"]<-"Wilson & Calanchini, 2022"
dt$Param[dt$Param=="Lai1"]<-"Lai et al., 2016 (Study 1)  "
dt$Param[dt$Param=="Lai2"]<-"Lai et al., 2016 (Study 2)  "
dt$Param[dt$Param=="Gawronski"]<-"Gawronski et al., 2017"
dt$Param[dt$Param=="Forscher"]<-"Forscher et al., 2017"

# indent the subgroup if there is a number in the placebo column
dt$Param <- ifelse(dt$type==0, 
                      dt$Param,
                      paste0(" ", dt$Param))

dt$` ` <- paste(rep(" ", 20), collapse = " ")
dt$`Recovery (95% CI)` <- ifelse(is.na(dt$Recov), "",
                             sprintf("%.2f [%.2f, %.2f]",
                                     dt$Recov, dt$CI.LB, dt$CI.UB))

dt2 <- pivot_wider(dt, id_cols = c("Param","id"),  names_from = c(Time), values_from = c(Recov,CI.LB,CI.UB,`Recovery (95% CI)`) )
dt2$`Recovery [95% CI]` <- ifelse(!is.na(dt2$`Recovery (95% CI)_Meta`), paste0("                 ",dt2$`Recovery (95% CI)_Meta`), paste0("T1 :", paste0(dt2$`Recovery (95% CI)_Time1`), " ; ", "T2: ", paste0(dt2$`Recovery (95% CI)_Time2`)))
dt2$` ` <- paste(rep(" ", 20), collapse = " ")


dt3<-dt2 %>% select(Param,Recov_Meta:11,15,16)

colnames(dt3)[colnames(dt3)=="Param"] <- "   "
colnames(dt3)[colnames(dt3)=="Recovery [95% CI]"] <- "    "

dt3$size_Meta <- ifelse(is.na(dt3$Recov_Meta), NA, 1.2)
dt3$size_T1 <- ifelse(is.na(dt3$Recov_Time1), NA, .6)
dt3$size_T2 <- ifelse(is.na(dt3$Recov_Time2), NA, .6)

# Set-up theme
tm <- forest_theme(
                   ci_pch = c(15, 16, 17),
                   ci_col = c("black","red","blue"),
                   ci_lty = c( "solid", "dashed", "dotted"),
                  # footnote_col = "blue",
                   legend_name = " ",
                  legend_position = "bottom",
                   legend_value = c("Meta-Analysis ", "Time 1 ", "Time 2 "))

library(forestploter)
p <- forest(
  dt3[c(1,12,11)],
            est = list(dt3$Recov_Meta, dt3$Recov_Time1, dt3$Recov_Time2),
            lower = list(dt3$CI.LB_Meta, dt3$CI.LB_Time1, dt3$CI.LB_Time2), 
            upper = list(dt3$CI.UB_Meta, dt3$CI.UB_Time1, dt3$CI.UB_Time2),
            ci_column = 2,
            ref_line = .7,
            xlim = c(-.1, 1),
            ticks_at = c(0, .2, .5, .7, 1),
  sizes = list(dt3$size_Meta, dt3$size_T1, dt3$size_T2),
  theme = tm
)
plot(p)


library(grid)
p <- edit_plot(p,
               row = seq(from=1,to=nrow(dt3),by=7),
               gp = gpar(fontface = c("bold","italic")
                         ), col = 1)

studyInds <- setdiff(1:nrow(dt3),seq(from=1,to=nrow(dt3),by=7))
paramInds <- seq(from=1,to=nrow(dt),by=7)

p <- edit_plot(p, row = studyInds, which = "background",
               gp = gpar(fill = "white"))
p <- edit_plot(p, row = paramInds, which = "background",
               gp = gpar(fill = "grey"))
png("~/Desktop/PD_RecovForest.png", units="in", width=10, height=18, res=300)
plot(p)
dev.off()
null device 
          1 
# ggsave function
ggplot2::ggsave(paste0(saveto,"PD_RecovForest.png"),
                dpi = 300,
                width = 8, height = 17, units = "in", plot=p)

ggplot2::ggsave(paste0(saveto,"PD_RecovForest.tiff"),
                dpi = 600,
                width = 8, height = 17, units = "in", plot=p)
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShncmlkKQpsaWJyYXJ5KGZvcmVzdHBsb3RlcikKbGlicmFyeSh0aWR5dmVyc2UpCmBgYAoKYGBge3J9CnNhdmV0byA8LSAiL1ZvbHVtZXMvUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L1Bsb3R0aW5nL1NhdmVkRmlncy8iCmBgYAoKCgpgYGB7cn0KcGF0aCA8LSAiL1ZvbHVtZXMvIgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9VQ1IvIikpCkNhbDEgPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNRdWFkVUNSMS5jc3YiLCBoZWFkZXIgPSBUKQpDYWwyIDwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUXVhZFVDUjIuY3N2IiwgaGVhZGVyID0gVCkKCmNvbG5hbWVzKENhbDEpWzI6bmNvbChDYWwxKV08LXBhc3RlKGNvbG5hbWVzKENhbDFbMjpuY29sKENhbDEpXSksIlQxIixzZXA9Il8iKQpjb2xuYW1lcyhDYWwyKVsyOm5jb2woQ2FsMildPC1wYXN0ZShjb2xuYW1lcyhDYWwyWzI6bmNvbChDYWwyKV0pLCJUMiIsc2VwPSJfIikKClEuQ2FsIDwtIG1lcmdlKENhbDEsIENhbDIsIGJ5ID0gInN1YmplY3QiLCBhbGwueCA9IFQsIGFsbC55ID0gVCkKCnNldHdkKHBhc3RlMChwYXRoLCJSZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvRXN0aW1hdGVzL1BJLyIpKQpQSTEgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUXVhZFByb2plY3RJbXBsaWNpdDEuY3N2IikKUEkyIDwtIHJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1F1YWRQcm9qZWN0SW1wbGljaXQyLmNzdiIpCgpjb2xuYW1lcyhQSTEpWzI6bmNvbChQSTEpXTwtcGFzdGUoY29sbmFtZXMoUEkxWzI6bmNvbChQSTEpXSksIlQxIixzZXA9Il8iKQpjb2xuYW1lcyhQSTIpWzI6bmNvbChQSTIpXTwtcGFzdGUoY29sbmFtZXMoUEkyWzI6bmNvbChQSTIpXSksIlQyIixzZXA9Il8iKQoKUS5QSSA8LSBtZXJnZShQSTEsIFBJMiwgYnkgPSAiSUQiLCBhbGwueCA9IFQsIGFsbC55ID0gVCkKCnNldHdkKHBhc3RlMChwYXRoLCJSZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvRXN0aW1hdGVzL0dhd3JvbnNraS8iKSkKR2F3MSA8LSByZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNRdWFkR2F3cm9uc2tpMS5jc3YiKQpHYXcyIDwtIHJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1F1YWRHYXdyb25za2kyLmNzdiIpCgpjb2xuYW1lcyhHYXcxKVsyOm5jb2woR2F3MSldPC1wYXN0ZShjb2xuYW1lcyhHYXcxWzI6bmNvbChHYXcxKV0pLCJUMSIsc2VwPSJfIikKY29sbmFtZXMoR2F3MilbMjpuY29sKEdhdzIpXTwtcGFzdGUoY29sbmFtZXMoR2F3MlsyOm5jb2woR2F3MildKSwiVDIiLHNlcD0iXyIpCgpRLkdhdyA8LSBtZXJnZShHYXcxLCBHYXcyLCBieSA9ICJjb2RlIiwgYWxsLnggPSBULCBhbGwueSA9IFQpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9Gb3JzY2hlci8iKSkKRm9yMTwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUXVhZEZvcnNjaGVyMS5jc3YiLCBoZWFkZXIgPSBUKQpGb3IyPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNRdWFkRm9yc2NoZXIyLmNzdiIsIGhlYWRlciA9IFQpCgpjb2xuYW1lcyhGb3IxKVsyOm5jb2woRm9yMSldPC1wYXN0ZShjb2xuYW1lcyhGb3IxWzI6bmNvbChGb3IxKV0pLCJUMSIsc2VwPSJfIikKY29sbmFtZXMoRm9yMilbMjpuY29sKEZvcjIpXTwtcGFzdGUoY29sbmFtZXMoRm9yMlsyOm5jb2woRm9yMildKSwiVDIiLHNlcD0iXyIpCgpRLkZvciA8LSBtZXJnZShGb3IxLCBGb3IyLCBieSA9ICJzdWJqZWN0IiwgYWxsLnggPSBULCBhbGwueSA9IFQpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9MYWkxLyIpKQpMYWkxMTwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzTGFpU3R1ZHkxUXVhZDEuY3N2IiwgaGVhZGVyID0gVCkKTGFpMTI8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0xhaVN0dWR5MVF1YWQyLmNzdiIsIGhlYWRlciA9IFQpCgpjb2xuYW1lcyhMYWkxMSlbMjpuY29sKExhaTExKV08LXBhc3RlKGNvbG5hbWVzKExhaTExWzI6bmNvbChMYWkxMSldKSwiVDEiLHNlcD0iXyIpCmNvbG5hbWVzKExhaTEyKVsyOm5jb2woTGFpMTIpXTwtcGFzdGUoY29sbmFtZXMoTGFpMTJbMjpuY29sKExhaTEyKV0pLCJUMiIsc2VwPSJfIikKClEuTGFpMSA8LSBtZXJnZShMYWkxMSwgTGFpMTIsIGJ5ID0gInNlc3Npb25faWQiLCBhbGwueCA9IFQsIGFsbC55ID0gVCkKCnNldHdkKHBhc3RlMChwYXRoLCJSZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvRXN0aW1hdGVzL0xhaTIvIikpCkxhaTIxPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNMYWlTdHVkeTJRdWFkMS5jc3YiLCBoZWFkZXIgPSBUKQpMYWkyMjwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzTGFpU3R1ZHkyUXVhZDIuY3N2IiwgaGVhZGVyID0gVCkKCmNvbG5hbWVzKExhaTIxKVsyOm5jb2woTGFpMjEpXTwtcGFzdGUoY29sbmFtZXMoTGFpMjFbMjpuY29sKExhaTIxKV0pLCJUMSIsc2VwPSJfIikKY29sbmFtZXMoTGFpMjIpWzI6bmNvbChMYWkyMildPC1wYXN0ZShjb2xuYW1lcyhMYWkyMlsyOm5jb2woTGFpMjIpXSksIlQyIixzZXA9Il8iKQoKUS5MYWkyIDwtIG1lcmdlKExhaTIxLCBMYWkyMiwgYnkgPSAic2Vzc2lvbl9pZCIsIGFsbC54ID0gVCwgYWxsLnkgPSBUKQoKY29sbmFtZXMoUS5DYWwpWzFdIDwtICJzdWJJRCIKUS5DYWwgPC0gY2JpbmQoUS5DYWwsIFN0dWR5ID0gIkNhbGFuY2hpbmkiKQpjb2xuYW1lcyhRLlBJKVsxXSA8LSAic3ViSUQiClEuUEkgPC0gY2JpbmQoUS5QSSwgU3R1ZHkgPSAiUEkiKQpjb2xuYW1lcyhRLkdhdylbMV0gPC0gInN1YklEIgpRLkdhdyA8LSBjYmluZChRLkdhdywgU3R1ZHkgPSAiR2F3cm9uc2tpIikKY29sbmFtZXMoUS5Gb3IpWzFdIDwtICJzdWJJRCIKUS5Gb3IgPC0gY2JpbmQoUS5Gb3IsIFN0dWR5ID0gIkZvcnNjaGVyIikKY29sbmFtZXMoUS5MYWkxKVsxXSA8LSAic3ViSUQiClEuTGFpMSA8LSBjYmluZChRLkxhaTEsIFN0dWR5ID0gIkxhaSAxIikKY29sbmFtZXMoUS5MYWkyKVsxXSA8LSAic3ViSUQiClEuTGFpMiA8LSBjYmluZChRLkxhaTIsIFN0dWR5ID0gIkxhaSAyIikKClF1YWQgPC0gcmJpbmQoUS5DYWwsUS5QSSxRLkdhdyxRLkZvcixRLkxhaTEsUS5MYWkyKQoKClF1YWQkU3R1ZHlbUXVhZCRTdHVkeT09IlBJIl08LSJQcm9qZWN0IEltcGxpY2l0LCAyMDIwIgpRdWFkJFN0dWR5W1F1YWQkU3R1ZHk9PSJDYWxhbmNoaW5pIl08LSJXaWxzb24gJiBDYWxhbmNoaW5pLCAyMDIyIgpRdWFkJFN0dWR5W1F1YWQkU3R1ZHk9PSJMYWkgMSJdPC0iTGFpIGV0IGFsLiwgMjAxNiAoU3R1ZHkgMSkgICIKUXVhZCRTdHVkeVtRdWFkJFN0dWR5PT0iTGFpIDIiXTwtIkxhaSBldCBhbC4sIDIwMTYgKFN0dWR5IDIpICAiClF1YWQkU3R1ZHlbUXVhZCRTdHVkeT09Ikdhd3JvbnNraSJdPC0iR2F3cm9uc2tpIGV0IGFsLiwgMjAxNyIKUXVhZCRTdHVkeVtRdWFkJFN0dWR5PT0iRm9yc2NoZXIiXTwtIkZvcnNjaGVyIGV0IGFsLiwgMjAxNyIKYGBgCgpgYGB7cn0KcGF0aCA8LSAiL1ZvbHVtZXMvIgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9VQ1IvIikpCkNhbDEgPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNQRFVDUjEuY3N2IiwgaGVhZGVyID0gVCkKQ2FsMiA8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1BEVUNSMi5jc3YiLCBoZWFkZXIgPSBUKQoKY29sbmFtZXMoQ2FsMSlbMjpuY29sKENhbDEpXTwtcGFzdGUoY29sbmFtZXMoQ2FsMVsyOm5jb2woQ2FsMSldKSwiVDEiLHNlcD0iXyIpCmNvbG5hbWVzKENhbDIpWzI6bmNvbChDYWwyKV08LXBhc3RlKGNvbG5hbWVzKENhbDJbMjpuY29sKENhbDIpXSksIlQyIixzZXA9Il8iKQoKUC5DYWwgPC0gbWVyZ2UoQ2FsMSwgQ2FsMiwgYnkgPSAic3ViamVjdCIsIGFsbC54ID0gVCwgYWxsLnkgPSBUKQoKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvUEkvIikpClBJMSA8LSByZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNQcm9qZWN0SW1wbGljaXRQRDEuY3N2IikKUEkyIDwtIHJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1Byb2plY3RJbXBsaWNpdFBEMi5jc3YiKQoKY29sbmFtZXMoUEkxKVsyOm5jb2woUEkxKV08LXBhc3RlKGNvbG5hbWVzKFBJMVsyOm5jb2woUEkxKV0pLCJUMSIsc2VwPSJfIikKY29sbmFtZXMoUEkyKVsyOm5jb2woUEkyKV08LXBhc3RlKGNvbG5hbWVzKFBJMlsyOm5jb2woUEkyKV0pLCJUMiIsc2VwPSJfIikKClAuUEkgPC0gbWVyZ2UoUEkxLCBQSTIsIGJ5ID0gIklEIiwgYWxsLnggPSBULCBhbGwueSA9IFQpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9HYXdyb25za2kvIikpCkdhdzEgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUERHYXdyb25za2kxLmNzdiIpCkdhdzIgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUERHYXdyb25za2kyLmNzdiIpCgpjb2xuYW1lcyhHYXcxKVsyOm5jb2woR2F3MSldPC1wYXN0ZShjb2xuYW1lcyhHYXcxWzI6bmNvbChHYXcxKV0pLCJUMSIsc2VwPSJfIikKY29sbmFtZXMoR2F3MilbMjpuY29sKEdhdzIpXTwtcGFzdGUoY29sbmFtZXMoR2F3MlsyOm5jb2woR2F3MildKSwiVDIiLHNlcD0iXyIpCgpQLkdhdyA8LSBtZXJnZShHYXcxLCBHYXcyLCBieSA9ICJjb2RlIiwgYWxsLnggPSBULCBhbGwueSA9IFQpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9Gb3JzY2hlci8iKSkKRm9yMTwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzRm9yc2NoZXJQRDEuY3N2IiwgaGVhZGVyID0gVCkKRm9yMjwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzRm9yc2NoZXJQRDIuY3N2IiwgaGVhZGVyID0gVCkKCmNvbG5hbWVzKEZvcjEpWzI6bmNvbChGb3IxKV08LXBhc3RlKGNvbG5hbWVzKEZvcjFbMjpuY29sKEZvcjEpXSksIlQxIixzZXA9Il8iKQpjb2xuYW1lcyhGb3IyKVsyOm5jb2woRm9yMildPC1wYXN0ZShjb2xuYW1lcyhGb3IyWzI6bmNvbChGb3IyKV0pLCJUMiIsc2VwPSJfIikKClAuRm9yIDwtIG1lcmdlKEZvcjEsIEZvcjIsIGJ5ID0gInN1YmplY3QiLCBhbGwueCA9IFQsIGFsbC55ID0gVCkKCnNldHdkKHBhc3RlMChwYXRoLCJSZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvRXN0aW1hdGVzL0xhaTEvIikpCkxhaTExPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNMYWlTdHVkeTFQRDEuY3N2IiwgaGVhZGVyID0gVCkKTGFpMTI8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0xhaVN0dWR5MVBEMi5jc3YiLCBoZWFkZXIgPSBUKQoKY29sbmFtZXMoTGFpMTEpWzI6bmNvbChMYWkxMSldPC1wYXN0ZShjb2xuYW1lcyhMYWkxMVsyOm5jb2woTGFpMTEpXSksIlQxIixzZXA9Il8iKQpjb2xuYW1lcyhMYWkxMilbMjpuY29sKExhaTEyKV08LXBhc3RlKGNvbG5hbWVzKExhaTEyWzI6bmNvbChMYWkxMildKSwiVDIiLHNlcD0iXyIpCgpQLkxhaTEgPC0gbWVyZ2UoTGFpMTEsIExhaTEyLCBieSA9ICJzZXNzaW9uX2lkIiwgYWxsLnggPSBULCBhbGwueSA9IFQpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9MYWkyLyIpKQpMYWkyMTwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzTGFpU3R1ZHkyUEQxLmNzdiIsIGhlYWRlciA9IFQpCkxhaTIyPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNMYWlTdHVkeTJQRDIuY3N2IiwgaGVhZGVyID0gVCkKCmNvbG5hbWVzKExhaTIxKVsyOm5jb2woTGFpMjEpXTwtcGFzdGUoY29sbmFtZXMoTGFpMjFbMjpuY29sKExhaTIxKV0pLCJUMSIsc2VwPSJfIikKY29sbmFtZXMoTGFpMjIpWzI6bmNvbChMYWkyMildPC1wYXN0ZShjb2xuYW1lcyhMYWkyMlsyOm5jb2woTGFpMjIpXSksIlQyIixzZXA9Il8iKQoKUC5MYWkyIDwtIG1lcmdlKExhaTIxLCBMYWkyMiwgYnkgPSAic2Vzc2lvbl9pZCIsIGFsbC54ID0gVCwgYWxsLnkgPSBUKQoKY29sbmFtZXMoUC5DYWwpWzFdIDwtICJzdWJJRCIKUC5DYWwgPC0gY2JpbmQoUC5DYWwsIFN0dWR5ID0gIkNhbGFuY2hpbmkiKQpjb2xuYW1lcyhQLlBJKVsxXSA8LSAic3ViSUQiClAuUEkgPC0gY2JpbmQoUC5QSSwgU3R1ZHkgPSAiUEkiKQpjb2xuYW1lcyhQLkdhdylbMV0gPC0gInN1YklEIgpQLkdhdyA8LSBjYmluZChQLkdhdywgU3R1ZHkgPSAiR2F3cm9uc2tpIikKY29sbmFtZXMoUC5Gb3IpWzFdIDwtICJzdWJJRCIKUC5Gb3IgPC0gY2JpbmQoUC5Gb3IsIFN0dWR5ID0gIkZvcnNjaGVyIikKY29sbmFtZXMoUC5MYWkxKVsxXSA8LSAic3ViSUQiClAuTGFpMSA8LSBjYmluZChQLkxhaTEsIFN0dWR5ID0gIkxhaSAxIikKY29sbmFtZXMoUC5MYWkyKVsxXSA8LSAic3ViSUQiClAuTGFpMiA8LSBjYmluZChQLkxhaTIsIFN0dWR5ID0gIkxhaSAyIikKClBEIDwtIHJiaW5kKFAuQ2FsLFAuUEksUC5HYXcsUC5Gb3IsUC5MYWkxLFAuTGFpMikKClBEJFN0dWR5W1BEJFN0dWR5PT0iUEkiXTwtIlByb2plY3QgSW1wbGljaXQsIDIwMjAiClBEJFN0dWR5W1BEJFN0dWR5PT0iQ2FsYW5jaGluaSJdPC0iV2lsc29uICYgQ2FsYW5jaGluaSwgMjAyMiIKUEQkU3R1ZHlbUEQkU3R1ZHk9PSJMYWkgMSJdPC0iTGFpIGV0IGFsLiwgMjAxNiAoU3R1ZHkgMSkgICIKUEQkU3R1ZHlbUEQkU3R1ZHk9PSJMYWkgMiJdPC0iTGFpIGV0IGFsLiwgMjAxNiAoU3R1ZHkgMikgICIKUEQkU3R1ZHlbUEQkU3R1ZHk9PSJHYXdyb25za2kiXTwtIkdhd3JvbnNraSBldCBhbC4sIDIwMTciClBEJFN0dWR5W1BEJFN0dWR5PT0iRm9yc2NoZXIiXTwtIkZvcnNjaGVyIGV0IGFsLiwgMjAxNyIKYGBgCgojIFF1YWQgTW9kZWwKCiMjIEFzc29jaWF0ZSBCbGFjay1CYWQKCmBgYHtyfQpBQ2JiU2NhdHRlciA8LSBnZ3Bsb3QoUXVhZCwgYWVzKHg9QUNiYjFfVDEsIHk9QUNiYjFfVDIsIGNvbG9yPVN0dWR5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgKyBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsgeWxpbSgwLDEpICsgeGxpbSgwLDEpICsgbGFicyh0aXRsZT0iQXNzb2NpYXRpb24gQmxhY2stQmFkIiwKICAgICAgIHg9IlRpbWUgMSIsIHkgPSAiVGltZSAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpICsKICBqdG9vbHM6OnRoZW1lX2FwYSgpIApBQ2JiU2NhdHRlcgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQUNiYlNjYXR0ZXIuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkFDYmJTY2F0dGVyLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIEFzc29jaWF0ZSBXaGl0ZS1Hb29kCgpgYGB7cn0KQUN3Z1NjYXR0ZXIgPC0gZ2dwbG90KFF1YWQsIGFlcyh4PUFDd2cxX1QxLCB5PUFDd2cxX1QyLCBjb2xvcj1TdHVkeSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJBc3NvY2lhdGlvbiBXaGl0ZS1Hb29kIiwKICAgICAgIHg9IlRpbWUgMSIsIHkgPSAiVGltZSAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpICsgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSA5KSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKQUN3Z1NjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkFDd2dTY2F0dGVyLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJBQ3dnU2NhdHRlci50aWZmIiksZHBpPTYwMCkKYGBgCgojIyBEZXRlY3Rpb24KCmBgYHtyfQpEU2NhdHRlciA8LSBnZ3Bsb3QoUXVhZCwgYWVzKHg9RDFfVDEsIHk9RDFfVDIsIGNvbG9yPVN0dWR5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkRldGVjdGlvbiIsCiAgICAgICB4PSJUaW1lIDEiLCB5ID0gIlRpbWUgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gOSkpICsKICBqdG9vbHM6OnRoZW1lX2FwYSgpCkRTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJEU2NhdHRlci5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiRFNjYXR0ZXIudGlmZiIpLGRwaT02MDApCmBgYAoKIyMgT3ZlcmNvbWluZyBCaWFzCgpgYGB7cn0KT0JTY2F0dGVyIDwtIGdncGxvdChRdWFkLCBhZXMoeD1PQjFfVDEsIHk9T0IxX1QyLCBjb2xvcj1TdHVkeSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJPdmVyY29taW5nIEJpYXMiLAogICAgICAgeD0iVGltZSAxIiwgeSA9ICJUaW1lIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKyB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDkpKSAgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKT0JTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJPQlNjYXR0ZXIuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIk9CU2NhdHRlci50aWZmIiksZHBpPTYwMCkKYGBgCgojIyBHdWVzc2luZwoKYGBge3J9CkdTY2F0dGVyIDwtIGdncGxvdChRdWFkLCBhZXMoeD1HMV9UMSwgeT1HMV9UMiwgY29sb3I9U3R1ZHkpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMikrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1UUlVFLAogICAgICAgICAgICAgY29sb3I9ImRhcmtncmV5IixhbHBoYT0xKSAgKyBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsgeWxpbSgwLDEpICsgeGxpbSgwLDEpICsgbGFicyh0aXRsZT0iR3Vlc3NpbmciLAogICAgICAgeD0iVGltZSAxIiwgeSA9ICJUaW1lIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkdTY2F0dGVyLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJHU2NhdHRlci50aWZmIiksZHBpPTYwMCkKYGBgCgojIyBQYW5lbAoKYGBge3J9CmxpYnJhcnkoZ2dwdWJyKQpRdWFkUGFuZWwxIDwtIGdnYXJyYW5nZShBQ3dnU2NhdHRlciwgQUNiYlNjYXR0ZXIsIERTY2F0dGVyLCBPQlNjYXR0ZXIsIEdTY2F0dGVyLAogICAgICAgICAgbmNvbCA9IDMsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCkKUXVhZFBhbmVsMQoKcmVxdWlyZShncmlkKSAgICMgZm9yIHRoZSB0ZXh0R3JvYigpIGZ1bmN0aW9uCgpRdWFkUGFuZWwyIDwtIGdnYXJyYW5nZShBQ3dnU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksIAogICAgICAgICAgICAgICAgICAgICAgICBBQ2JiU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgRFNjYXR0ZXIgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksCiAgICAgICAgICAgICAgICAgICAgICAgIE9CU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgR1NjYXR0ZXIgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksCiAgICAgICAgICBuY29sID0gMywgbnJvdyA9IDIsIGNvbW1vbi5sZWdlbmQgPSBULCBsYWJlbHMgPSBOVUxMLCBsZWdlbmQgPSAiYm90dG9tIiwKICAgICAgICAgIGFsaWduID0gImh2IiwgCiAgICAgICAgICAgICAgICAgICAgZm9udC5sYWJlbCA9IGxpc3Qoc2l6ZSA9IDEwLCBjb2xvciA9ICJibGFjayIsIGZhY2UgPSAiYm9sZCIsIGZhbWlseSA9IE5VTEwsIHBvc2l0aW9uID0gInRvcCIpKQpRdWFkUGFuZWwyCgphbm5vdGF0ZV9maWd1cmUoUXVhZFBhbmVsMiwgbGVmdCA9IHRleHRHcm9iKCJUaW1lIDIiLCByb3QgPSA5MCwgdmp1c3QgPSAxLCBoanVzdCA9IDAsIGdwID0gZ3BhcihjZXggPSAxKSksCiAgICAgICAgICAgICAgICAgICAgYm90dG9tID0gdGV4dEdyb2IoIlRpbWUgMSIsIHZqdXN0ID0gLTYuNSwgZ3AgPSBncGFyKGNleCA9IDEpKSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAsLTEpKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiUXVhZFBhbmVsLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJRdWFkUGFuZWwudGlmZiIpLGRwaT02MDApCmBgYAoKCiMgUEQgTW9kZWwKCiMjIEF1dG9tYXRpYyBCbGFjawoKYGBge3J9CkFiU2NhdHRlciA8LSBnZ3Bsb3QoUEQsIGFlcyh4PUFiMV9UMSwgeT1BYjFfVDIsIGNvbG9yPVN0dWR5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkF1dG9tYXRpYyBCbGFjayIsCiAgICAgICB4PSJUaW1lIDEiLCB5ID0gIlRpbWUgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpBYlNjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkFiU2NhdHRlci5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQWJTY2F0dGVyLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIEFzc29jaWF0ZSBXaGl0ZQoKYGBge3J9CkF3U2NhdHRlciA8LSBnZ3Bsb3QoUEQsIGFlcyh4PUF3MV9UMSwgeT1BdzFfVDIsIGNvbG9yPVN0dWR5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkF1dG9tYXRpYyBXaGl0ZSIsCiAgICAgICB4PSJUaW1lIDEiLCB5ID0gIlRpbWUgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpBd1NjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkF3U2NhdHRlci5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQXdTY2F0dGVyLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIENvbnRyb2wgR29vZAoKYGBge3J9CkNwU2NhdHRlciA8LSBnZ3Bsb3QoUEQsIGFlcyh4PUNwMV9UMSwgeT1DcDFfVDIsIGNvbG9yPVN0dWR5KSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkNvbnRyb2wgR29vZCIsCiAgICAgICB4PSJUaW1lIDEiLCB5ID0gIlRpbWUgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpDcFNjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkNwU2NhdHRlci5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQ3BTY2F0dGVyLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIENvbnRyb2wgQmFkCgpgYGB7cn0KQ3VTY2F0dGVyIDwtIGdncGxvdChQRCwgYWVzKHg9Q3UxX1QxLCB5PUN1MV9UMiwgY29sb3I9U3R1ZHkpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMikrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1UUlVFLAogICAgICAgICAgICAgY29sb3I9ImRhcmtncmV5IixhbHBoYT0xKSAgKyBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsgeWxpbSgwLDEpICsgeGxpbSgwLDEpICsgbGFicyh0aXRsZT0iQ29udHJvbCBCYWQiLAogICAgICAgeD0iVGltZSAxIiwgeSA9ICJUaW1lIDIiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKQ3VTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJDdVNjYXR0ZXIuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkN1U2NhdHRlci50aWZmIiksZHBpPTYwMCkKYGBgCgojIyBDb250cm9sIFdoaXRlCgpgYGB7cn0KQ3dTY2F0dGVyIDwtIGdncGxvdChQRCwgYWVzKHg9Q3cxX1QxLCB5PUN3MV9UMiwgY29sb3I9U3R1ZHkpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMikrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1UUlVFLAogICAgICAgICAgICAgY29sb3I9ImRhcmtncmV5IixhbHBoYT0xKSAgKyBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsgeWxpbSgwLDEpICsgeGxpbSgwLDEpICsgbGFicyh0aXRsZT0iQ29udHJvbCBXaGl0ZSIsCiAgICAgICB4PSJUaW1lIDEiLCB5ID0gIlRpbWUgMiIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpDd1NjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkN3U2NhdHRlci5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQ3dTY2F0dGVyLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIENvbnRyb2wgQmxhY2sKCmBgYHtyfQpDYlNjYXR0ZXIgPC0gZ2dwbG90KFBELCBhZXMoeD1DYjFfVDEsIHk9Q2IxX1QyLCBjb2xvcj1TdHVkeSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJDb250cm9sIEJsYWNrIiwKICAgICAgIHg9IlRpbWUgMSIsIHkgPSAiVGltZSAyIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpICsKICBqdG9vbHM6OnRoZW1lX2FwYSgpCkNiU2NhdHRlcgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQ2JTY2F0dGVyLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJDYlNjYXR0ZXIudGlmZiIpLGRwaT02MDApCmBgYAoKIyMgUGFuZWwKCmBgYHtyfQpsaWJyYXJ5KGdncHVicikKUERQYW5lbDEgPC0gZ2dhcnJhbmdlKEF3U2NhdHRlciwgQWJTY2F0dGVyLCBDdVNjYXR0ZXIsIENwU2NhdHRlciwgQ2JTY2F0dGVyLCBDd1NjYXR0ZXIsCiAgICAgICAgICBuY29sID0gMywgbnJvdyA9IDIsIGNvbW1vbi5sZWdlbmQgPSBUKQpQRFBhbmVsMQoKcmVxdWlyZShncmlkKSAgICMgZm9yIHRoZSB0ZXh0R3JvYigpIGZ1bmN0aW9uCgpQRFBhbmVsMiA8LSBnZ2FycmFuZ2UoQXdTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICArIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksIAogICAgICAgICAgICAgICAgICAgICAgICBBYlNjYXR0ZXIgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksCiAgICAgICAgICAgICAgICAgICAgICAgIEN1U2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgQ3BTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICsgcnJlbW92ZSgieWxhYiIpICsgcnJlbW92ZSgieGxhYiIpLAogICAgICAgICAgICAgICAgICAgICAgICBDYlNjYXR0ZXIgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksCiAgICAgICAgICAgICAgICAgICAgICAgIEN3U2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgIG5jb2wgPSAzLCBucm93ID0gMiwgY29tbW9uLmxlZ2VuZCA9IFQsIGxhYmVscyA9IE5VTEwsIGxlZ2VuZCA9ICJib3R0b20iLAogICAgICAgICAgYWxpZ24gPSAiaHYiLCAKICAgICAgICAgICAgICAgICAgICBmb250LmxhYmVsID0gbGlzdChzaXplID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmFjZSA9ICJib2xkIiwgZmFtaWx5ID0gTlVMTCwgcG9zaXRpb24gPSAidG9wIikpClBEUGFuZWwyIDwtIGFubm90YXRlX2ZpZ3VyZShQRFBhbmVsMiwgbGVmdCA9IHRleHRHcm9iKCJUaW1lIDIiLCByb3QgPSA5MCwgdmp1c3QgPSAxLCBoanVzdCA9IDAsIGdwID0gZ3BhcihjZXggPSAxKSksCiAgICAgICAgICAgICAgICAgICAgYm90dG9tID0gdGV4dEdyb2IoIlRpbWUgMSIsIHZqdXN0ID0gLTYuNSwgZ3AgPSBncGFyKGNleCA9IDEpKSkgKyB0aGVtZShsZWdlbmQucG9zaXRpb24gPSBjKDAsLTEpKQpQRFBhbmVsMgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiUERQYW5lbC5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiUERQYW5lbC50aWZmIiksZHBpPTYwMCkKYGBgCgojIFJlbGlhYmlsaXR5IE1ldGEtQW5hbHlzaXMKCmBgYHtyfQpkdCA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvR2l0SHViL01QVC1SZWxpYWJpbGl0eS9SZXRlc3Qvb3V0cHV0L2NvbWJRdWFkX0RmLmNzdiIpWzI6Nl0KCmR0JFBhcmFtW2R0JFBhcmFtPT0iRCJdPC0iRGV0ZWN0aW9uIgpkdCRQYXJhbVtkdCRQYXJhbT09Ik9CIl08LSJPdmVyY29taW5nIEJpYXMiCmR0JFBhcmFtW2R0JFBhcmFtPT0iQUNiYiJdPC0iQXNzb2NpYXRpb24gQmxhY2stQmFkIgpkdCRQYXJhbVtkdCRQYXJhbT09IkFDd2ciXTwtIkFzc29jaWF0aW9uIFdoaXRlLUdvb2QiCmR0JFBhcmFtW2R0JFBhcmFtPT0iRyJdPC0iR3Vlc3NpbmciCgpkdCRQYXJhbVtkdCRQYXJhbT09IlBJIl08LSJQcm9qZWN0IEltcGxpY2l0LCAyMDIwIgpkdCRQYXJhbVtkdCRQYXJhbT09IkNhbGFuY2hpbmkiXTwtIldpbHNvbiAmIENhbGFuY2hpbmksIDIwMjIiCmR0JFBhcmFtW2R0JFBhcmFtPT0iTGFpMSJdPC0iTGFpIGV0IGFsLiwgMjAxNiAoU3R1ZHkgMSkgICIKZHQkUGFyYW1bZHQkUGFyYW09PSJMYWkyIl08LSJMYWkgZXQgYWwuLCAyMDE2IChTdHVkeSAyKSAgIgpkdCRQYXJhbVtkdCRQYXJhbT09Ikdhd3JvbnNraSJdPC0iR2F3cm9uc2tpIGV0IGFsLiwgMjAxNyIKZHQkUGFyYW1bZHQkUGFyYW09PSJGb3JzY2hlciJdPC0iRm9yc2NoZXIgZXQgYWwuLCAyMDE3IgoKIyBpbmRlbnQgdGhlIHN1Ymdyb3VwIGlmIHRoZXJlIGlzIGEgbnVtYmVyIGluIHRoZSBwbGFjZWJvIGNvbHVtbgpkdCRQYXJhbSA8LSBpZmVsc2UoZHQkdHlwZT09MCwgCiAgICAgICAgICAgICAgICAgICAgICBkdCRQYXJhbSwKICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiICIsIGR0JFBhcmFtKSkKCmNvbG5hbWVzKGR0KVtjb2xuYW1lcyhkdCk9PSJQYXJhbSJdIDwtICIgICAiCmR0JGAgYCA8LSBwYXN0ZShyZXAoIiAiLCAyMCksIGNvbGxhcHNlID0gIiAiKQpkdCRgSUNDICg5NSUgQ0kpYCA8LSBpZmVsc2UoaXMubmEoZHQkSUNDKSwgIiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3ByaW50ZigiJS4yZiBbJS4yZiwgJS4yZl0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZHQkSUNDLCBkdCRDSS5MQiwgZHQkQ0kuVUIpKQoKCmR0JElDQ3N0dWR5IDwtIGlmZWxzZShkdCR0eXBlPT0xLCBkdCRJQ0MsIE5BKQpkdCRJQ0MuTEJzdHVkeSA8LSBpZmVsc2UoZHQkdHlwZT09MSwgZHQkQ0kuTEIsIE5BKQpkdCRJQ0MuVUJzdHVkeSA8LSBpZmVsc2UoZHQkdHlwZT09MSwgZHQkQ0kuVUIsIE5BKQpkdCRTaXplc3R1ZHkgPC0gaWZlbHNlKGR0JHR5cGU9PTEsIC42LCBOQSkKZHQkU2l6ZW1ldGEgPC0gaWZlbHNlKGR0JHR5cGU9PTAsIDEuMiwgTkEpCmR0JElDQ21ldGEgPC0gaWZlbHNlKGR0JHR5cGU9PTAsIGR0JElDQywgTkEpCmR0JElDQy5MQm1ldGEgPC0gaWZlbHNlKGR0JHR5cGU9PTAsIGR0JENJLkxCLCBOQSkKZHQkSUNDLlVCbWV0YSA8LSBpZmVsc2UoZHQkdHlwZT09MCwgZHQkQ0kuVUIsIE5BKQoKI2R0PC1kdFtjKDE6NCw2OjcpXQpkdDwtZHRbYygxOjQsNjpuY29sKGR0KSldCmNvbG5hbWVzKGR0KVtjb2xuYW1lcyhkdCk9PSJJQ0MgKDk1JSBDSSkiXSA8LSAiICAgICAiCgpsaWJyYXJ5KGZvcmVzdHBsb3RlcikKIyBwIDwtIGZvcmVzdCgKIyAgIGR0W2MoMSw1LDYpXSwKIyAgICAgICAgICAgICBlc3QgPSBkdCRJQ0MsCiMgICAgICAgICAgICAgbG93ZXIgPSBkdCRDSS5MQiwgCiMgICAgICAgICAgICAgdXBwZXIgPSBkdCRDSS5VQiwKIyAgICAgICAgICAgICBjaV9jb2x1bW4gPSAyLAojICAgICAgICAgICAgIHJlZl9saW5lID0gLjQsCiMgICAgICAgICAgICAgeGxpbSA9IGMoLS4xLCAxKSwKIyAgICAgICAgICAgICB0aWNrc19hdCA9IGMoMCwgLjQsLjYsIC43NSwgMSksCiMgICBzaXplcyA9IC4xCiMgKQoKdG0gPC0gZm9yZXN0X3RoZW1lKAogICAgICAgICAgICAgICAgICAgY2lfcGNoID0gYygxNSwgMTYpLAogICAgICAgICAgICAgICAgICAgY2lfY29sID0gYygiYmxhY2siLCJyZWQiKSwKICAgICAgICAgICAgICAgICAgIGNpX2x0eSA9IGMoICJzb2xpZCIsICJkYXNoZWQiKSwKICAgICAgICAgICAgICAgICAgIyBmb290bm90ZV9jb2wgPSAiYmx1ZSIsCiAgICAgICAgICAgICAgICAgICBsZWdlbmRfbmFtZSA9ICIgIiwKICAgICAgICAgICAgICAgICAgbGVnZW5kX3Bvc2l0aW9uID0gImJvdHRvbSIsCiAgICAgICAgICAgICAgICAgICBsZWdlbmRfdmFsdWUgPSBjKCJNZXRhLUFuYWx5c2lzICIsICJTdHVkeSIpCiAgICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgICApCgpwIDwtIGZvcmVzdCgKICBkdFtjKDEsNSw2KV0sCiAgICAgICAgICAgIGVzdCA9IGxpc3QoZHQkSUNDbWV0YSwgZHQkSUNDc3R1ZHkpLAogICAgICAgICAgICBsb3dlciA9IGxpc3QoZHQkSUNDLkxCbWV0YSwgZHQkSUNDLkxCc3R1ZHkpLCAKICAgICAgICAgICAgdXBwZXIgPSBsaXN0KGR0JElDQy5VQm1ldGEsIGR0JElDQy5VQnN0dWR5KSwKICAgICAgICAgICAgICBjaV9jb2x1bW4gPSAyLAogICAgICAgICAgICByZWZfbGluZSA9IC40LAogICAgICAgICAgICB4bGltID0gYygtLjEsIDEpLAogICAgICAgICAgICB0aWNrc19hdCA9IGMoMCwgLjQsLjYsIC43NSwgMSksCiAgc2l6ZXMgPSBsaXN0KGR0JFNpemVtZXRhLCBkdCRTaXplc3R1ZHkpLAogIHRoZW1lID0gdG0KKQoKbGlicmFyeShncmlkKQpwIDwtIGVkaXRfcGxvdChwLAogICAgICAgICAgICAgICByb3cgPSBzZXEoZnJvbT0xLHRvPW5yb3coZHQpLGJ5PTcpLAogICAgICAgICAgICAgICBncCA9IGdwYXIoZm9udGZhY2UgPSBjKCJib2xkIiwiaXRhbGljIikKICAgICAgICAgICAgICAgICAgICAgICAgICksIGNvbCA9IDEpCgpzdHVkeUluZHMgPC0gc2V0ZGlmZigxOm5yb3coZHQpLHNlcShmcm9tPTEsdG89bnJvdyhkdCksYnk9NykpCnBhcmFtSW5kcyA8LSBzZXEoZnJvbT0xLHRvPW5yb3coZHQpLGJ5PTcpCgpwIDwtIGVkaXRfcGxvdChwLCByb3cgPSBzdHVkeUluZHMsIHdoaWNoID0gImJhY2tncm91bmQiLAogICAgICAgICAgICAgICBncCA9IGdwYXIoZmlsbCA9ICJ3aGl0ZSIpKQpwIDwtIGVkaXRfcGxvdChwLCByb3cgPSBwYXJhbUluZHMsIHdoaWNoID0gImJhY2tncm91bmQiLAogICAgICAgICAgICAgICBncCA9IGdwYXIoZmlsbCA9ICJncmV5IikpCgpgYGAKCgoKYGBge3J9CnBuZyhwYXN0ZTAoc2F2ZXRvLCJRdWFkX1RSVC5wbmciKSwgdW5pdHM9ImluIiwgd2lkdGg9MTAsIGhlaWdodD0xMiwgcmVzPTMwMCkKcGxvdChwKQpkZXYub2ZmKCkKYGBgCgoKYGBge3J9CiMgZ2dzYXZlIGZ1bmN0aW9uCmdncGxvdDI6Omdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJRdWFkX1RSVC5wbmciKSwKICAgICAgICAgICAgICAgIGRwaSA9IDMwMCwKICAgICAgICAgICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gMTEsIHVuaXRzID0gImluIiwgcGxvdD1wKQoKZ2dwbG90Mjo6Z2dzYXZlKHBhc3RlMChzYXZldG8sIlF1YWRfVFJULnRpZmYiKSwKICAgICAgICAgICAgICAgIGRwaSA9IDYwMCwKICAgICAgICAgICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gMTEsIHVuaXRzID0gImluIiwgcGxvdD1wKQpgYGAKCmBgYHtyfQpkdCA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvR2l0SHViL01QVC1SZWxpYWJpbGl0eS9SZXRlc3Qvb3V0cHV0L2NvbWJQRF9EZi5jc3YiKVsyOjZdCgpkdCRQYXJhbVtkdCRQYXJhbT09IkFiIl08LSJBdXRvbWF0aWMgQmxhY2siCmR0JFBhcmFtW2R0JFBhcmFtPT0iQXciXTwtIkF1dG9tYXRpYyBXaGl0ZSIKZHQkUGFyYW1bZHQkUGFyYW09PSJDYiJdPC0iQ29udHJvbCBCbGFjayIKZHQkUGFyYW1bZHQkUGFyYW09PSJDdyJdPC0iQ29udHJvbCBXaGl0ZSIKZHQkUGFyYW1bZHQkUGFyYW09PSJDdSJdPC0iQ29udHJvbCBCYWQiCmR0JFBhcmFtW2R0JFBhcmFtPT0iQ3AiXTwtIkNvbnRyb2wgR29vZCIKCmR0JFBhcmFtW2R0JFBhcmFtPT0iUEkiXTwtIlByb2plY3QgSW1wbGljaXQsIDIwMjAiCmR0JFBhcmFtW2R0JFBhcmFtPT0iQ2FsYW5jaGluaSJdPC0iV2lsc29uICYgQ2FsYW5jaGluaSwgMjAyMiIKZHQkUGFyYW1bZHQkUGFyYW09PSJMYWkxIl08LSJMYWkgZXQgYWwuLCAyMDE2IChTdHVkeSAxKSAgIgpkdCRQYXJhbVtkdCRQYXJhbT09IkxhaTIiXTwtIkxhaSBldCBhbC4sIDIwMTYgKFN0dWR5IDIpICAiCmR0JFBhcmFtW2R0JFBhcmFtPT0iR2F3cm9uc2tpIl08LSJHYXdyb25za2kgZXQgYWwuLCAyMDE3IgpkdCRQYXJhbVtkdCRQYXJhbT09IkZvcnNjaGVyIl08LSJGb3JzY2hlciBldCBhbC4sIDIwMTciCgojIGluZGVudCB0aGUgc3ViZ3JvdXAgaWYgdGhlcmUgaXMgYSBudW1iZXIgaW4gdGhlIHBsYWNlYm8gY29sdW1uCmR0JFBhcmFtIDwtIGlmZWxzZShkdCR0eXBlPT0wLCAKICAgICAgICAgICAgICAgICAgICAgIGR0JFBhcmFtLAogICAgICAgICAgICAgICAgICAgICAgcGFzdGUwKCIgIiwgZHQkUGFyYW0pKQoKY29sbmFtZXMoZHQpW2NvbG5hbWVzKGR0KT09IlBhcmFtIl0gPC0gIiAgICIKY29sbmFtZXMoZHQpW2NvbG5hbWVzKGR0KT09IlBhcmFtIl0gPC0gIiAgICIKZHQkYCBgIDwtIHBhc3RlKHJlcCgiICIsIDIwKSwgY29sbGFwc2UgPSAiICIpCmR0JGBJQ0MgKDk1JSBDSSlgIDwtIGlmZWxzZShpcy5uYShkdCRJQ0MpLCAiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCIlLjJmIFslLjJmLCAlLjJmXSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdCRJQ0MsIGR0JENJLkxCLCBkdCRDSS5VQikpCgpkdCRJQ0NzdHVkeSA8LSBpZmVsc2UoZHQkdHlwZT09MSwgZHQkSUNDLCBOQSkKZHQkSUNDLkxCc3R1ZHkgPC0gaWZlbHNlKGR0JHR5cGU9PTEsIGR0JENJLkxCLCBOQSkKZHQkSUNDLlVCc3R1ZHkgPC0gaWZlbHNlKGR0JHR5cGU9PTEsIGR0JENJLlVCLCBOQSkKZHQkU2l6ZXN0dWR5IDwtIGlmZWxzZShkdCR0eXBlPT0xLCAuNiwgTkEpCmR0JFNpemVtZXRhIDwtIGlmZWxzZShkdCR0eXBlPT0wLCAxLjIsIE5BKQpkdCRJQ0NtZXRhIDwtIGlmZWxzZShkdCR0eXBlPT0wLCBkdCRJQ0MsIE5BKQpkdCRJQ0MuTEJtZXRhIDwtIGlmZWxzZShkdCR0eXBlPT0wLCBkdCRDSS5MQiwgTkEpCmR0JElDQy5VQm1ldGEgPC0gaWZlbHNlKGR0JHR5cGU9PTAsIGR0JENJLlVCLCBOQSkKCiNkdDwtZHRbYygxOjQsNjo3KV0KZHQ8LWR0W2MoMTo0LDY6bmNvbChkdCkpXQpjb2xuYW1lcyhkdClbY29sbmFtZXMoZHQpPT0iSUNDICg5NSUgQ0kpIl0gPC0gIiAgICAgIgoKbGlicmFyeShmb3Jlc3RwbG90ZXIpCiMgcCA8LSBmb3Jlc3QoCiMgICBkdFtjKDEsNSw2KV0sCiMgICAgICAgICAgICAgZXN0ID0gZHQkSUNDLAojICAgICAgICAgICAgIGxvd2VyID0gZHQkQ0kuTEIsIAojICAgICAgICAgICAgIHVwcGVyID0gZHQkQ0kuVUIsCiMgICAgICAgICAgICAgY2lfY29sdW1uID0gMiwKIyAgICAgICAgICAgICByZWZfbGluZSA9IC40LAojICAgICAgICAgICAgIHhsaW0gPSBjKC0uMSwgMSksCiMgICAgICAgICAgICAgdGlja3NfYXQgPSBjKDAsIC40LC42LCAuNzUsIDEpLAojICAgc2l6ZXMgPSAuMQojICkKCnRtIDwtIGZvcmVzdF90aGVtZSgKICAgICAgICAgICAgICAgICAgIGNpX3BjaCA9IGMoMTUsIDE2KSwKICAgICAgICAgICAgICAgICAgIGNpX2NvbCA9IGMoImJsYWNrIiwicmVkIiksCiAgICAgICAgICAgICAgICAgICBjaV9sdHkgPSBjKCAic29saWQiLCAiZGFzaGVkIiksCiAgICAgICAgICAgICAgICAgICMgZm9vdG5vdGVfY29sID0gImJsdWUiLAogICAgICAgICAgICAgICAgICAgbGVnZW5kX25hbWUgPSAiICIsCiAgICAgICAgICAgICAgICAgIGxlZ2VuZF9wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgICAgICAgICAgbGVnZW5kX3ZhbHVlID0gYygiTWV0YS1BbmFseXNpcyAiLCAiU3R1ZHkiKQogICAgICAgICAgICAgICAgICAKICAgICAgICAgICAgICAgICAgKQoKcCA8LSBmb3Jlc3QoCiAgZHRbYygxLDUsNildLAogICAgICAgICAgICBlc3QgPSBsaXN0KGR0JElDQ21ldGEsIGR0JElDQ3N0dWR5KSwKICAgICAgICAgICAgbG93ZXIgPSBsaXN0KGR0JElDQy5MQm1ldGEsIGR0JElDQy5MQnN0dWR5KSwgCiAgICAgICAgICAgIHVwcGVyID0gbGlzdChkdCRJQ0MuVUJtZXRhLCBkdCRJQ0MuVUJzdHVkeSksCiAgICAgICAgICAgICAgY2lfY29sdW1uID0gMiwKICAgICAgICAgICAgcmVmX2xpbmUgPSAuNCwKICAgICAgICAgICAgeGxpbSA9IGMoLS4xLCAxKSwKICAgICAgICAgICAgdGlja3NfYXQgPSBjKDAsIC40LC42LCAuNzUsIDEpLAogIHNpemVzID0gbGlzdChkdCRTaXplbWV0YSwgZHQkU2l6ZXN0dWR5KSwKICB0aGVtZSA9IHRtCikKCmxpYnJhcnkoZ3JpZCkKcCA8LSBlZGl0X3Bsb3QocCwKICAgICAgICAgICAgICAgcm93ID0gc2VxKGZyb209MSx0bz1ucm93KGR0KSxieT03KSwKICAgICAgICAgICAgICAgZ3AgPSBncGFyKGZvbnRmYWNlID0gYygiYm9sZCIsIml0YWxpYyIpCiAgICAgICAgICAgICAgICAgICAgICAgICApLCBjb2wgPSAxKQoKc3R1ZHlJbmRzIDwtIHNldGRpZmYoMTpucm93KGR0KSxzZXEoZnJvbT0xLHRvPW5yb3coZHQpLGJ5PTcpKQpwYXJhbUluZHMgPC0gc2VxKGZyb209MSx0bz1ucm93KGR0KSxieT03KQoKcCA8LSBlZGl0X3Bsb3QocCwgcm93ID0gc3R1ZHlJbmRzLCB3aGljaCA9ICJiYWNrZ3JvdW5kIiwKICAgICAgICAgICAgICAgZ3AgPSBncGFyKGZpbGwgPSAid2hpdGUiKSkKcCA8LSBlZGl0X3Bsb3QocCwgcm93ID0gcGFyYW1JbmRzLCB3aGljaCA9ICJiYWNrZ3JvdW5kIiwKICAgICAgICAgICAgICAgZ3AgPSBncGFyKGZpbGwgPSAiZ3JleSIpKQoKYGBgCgoKCmBgYHtyfQpwbmcocGFzdGUwKHNhdmV0bywiUERQX1RSVC5wbmciKSwgdW5pdHM9ImluIiwgd2lkdGg9MTAsIGhlaWdodD0xNSwgcmVzPTMwMCkKcGxvdChwKQpkZXYub2ZmKCkKYGBgCgpgYGB7cn0KIyBnZ3NhdmUgZnVuY3Rpb24KZ2dwbG90Mjo6Z2dzYXZlKHBhc3RlMChzYXZldG8sIlBEUF9UUlQucG5nIiksCiAgICAgICAgICAgICAgICBkcGkgPSAzMDAsCiAgICAgICAgICAgICAgICB3aWR0aCA9IDYsIGhlaWdodCA9IDEzLCB1bml0cyA9ICJpbiIsIHBsb3Q9cCkKCmdncGxvdDI6Omdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJQRFBfVFJULnRpZmYiKSwKICAgICAgICAgICAgICAgIGRwaSA9IDYwMCwKICAgICAgICAgICAgICAgIHdpZHRoID0gNiwgaGVpZ2h0ID0gMTMsIHVuaXRzID0gImluIiwgcGxvdD1wKQpgYGAKCgojIFJlY292ZXJ5CgpgYGB7cn0Kc2V0d2QocGFzdGUwKCIvVm9sdW1lcy9SZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvUmVjb3ZlcnkvUmVjb3ZlcmVkUGFyYW1zL1BELyIpKQp0aW1lczwtYygiVGltZTEiLCJUaW1lMiIpCgphbGxyZWNvdnMgPC0gYXMuZGF0YS5mcmFtZShtYXRyaXgobmNvbD0xNCxucm93PTApKQoKUERkaXJzIDwtIGxpc3QuZGlycyhwYXRoID0gIi4iLCBmdWxsLm5hbWVzID0gVFJVRSwgcmVjdXJzaXZlID0gVFJVRSlbLTFdCmZvcihkIGluIFBEZGlycyl7CiAgZm9yKHRpIGluIHRpbWVzKXsKICAgIGN1ckZpbGVzIDwtIGxpc3QuZmlsZXMocGF0aD1kLHBhdHRlcm49IlxcLmNzdiQiKQogICAgaWQ8LWdyZXAodGksY3VyRmlsZXMpCiAgICBvdXRwdXQ8LXJlYWQuY3N2KHBhc3RlMChkLCIvIixjdXJGaWxlc1tpZF0pKQogICAgbmFtZTwtZ3N1YigiLi8iLCIiLGQpCiAgICBuYW1lPC1nc3ViKCIgIiwiIixuYW1lKQogICAgCiAgICBpZih0aT09IlRpbWUxIil7CiAgICAgICNjb2xuYW1lcyhvdXRwdXQpIDwtIHBhc3RlKGNvbG5hbWVzKG91dHB1dCksIlQxIixzZXA9Il8iKQogICAgICBvdXRwdXQkdGltZSA8LSAiVDEiCiAgICB9ZWxzZSBpZih0aT09IlRpbWUyIil7CiAgICAgICNjb2xuYW1lcyhvdXRwdXQpIDwtIHBhc3RlKGNvbG5hbWVzKG91dHB1dCksIlQyIixzZXA9Il8iKQogICAgICBvdXRwdXQkdGltZSA8LSAiVDIiCiAgICB9CiAgICAKICAgIGFzc2lnbihwYXN0ZTAobmFtZSwiLlBELlJlY292LiIsdGkpLG91dHB1dCkKICB9CiAgZGYgPC0gcmJpbmQoZ2V0KHBhc3RlMChuYW1lLCIuUEQuUmVjb3YuVGltZTEiKSksZ2V0KHBhc3RlMChuYW1lLCIuUEQuUmVjb3YuVGltZTIiKSkpCiAgYXNzaWduKHBhc3RlMChuYW1lLCIuUEQuUmVjb3YiKSxkZikKICBhbGxyZWNvdnMgPC0gcmJpbmQoYWxscmVjb3ZzLGNiaW5kKGRmLFN0dWR5PW5hbWUpKQp9CgoKYWxscmVjb3ZzJFN0dWR5IDwtIGdzdWIoIkxhaTEiLCAiTGFpIDEiLCBhbGxyZWNvdnMkU3R1ZHkpCmFsbHJlY292cyRTdHVkeSA8LSBnc3ViKCJMYWkyIiwgIkxhaSAyIiwgYWxscmVjb3ZzJFN0dWR5KQpQRC5yZWNvdnMgPC0gYWxscmVjb3ZzClBELnJlY292cyA8LSBkcGx5cjo6cmVuYW1lKFBELnJlY292cywgc3ViSUQ9WCkKCnRhcHBseShQRC5yZWNvdnMkQWIxLCBQRC5yZWNvdnMkU3R1ZHksIGZ1bmN0aW9uKHgpIGxlbmd0aCh4KSkKYGBgCgpgYGB7cn0KcGF0aCA8LSAiL1ZvbHVtZXMvIgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9VQ1IvIikpCkNhbDEgPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNQRFVDUjEuY3N2IiwgaGVhZGVyID0gVCkKQ2FsMiA8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1BEVUNSMi5jc3YiLCBoZWFkZXIgPSBUKQoKQ2FsMSR0aW1lIDwtICJUMSIKQ2FsMiR0aW1lIDwtICJUMiIKQ2FsMSRzdWJJRCA8LSAxOm5yb3coQ2FsMSkKQ2FsMiRzdWJJRCA8LSAxOm5yb3coQ2FsMikKUC5DYWwgPC0gcmJpbmQoQ2FsMSwgQ2FsMikKCnNldHdkKHBhc3RlMChwYXRoLCJSZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvRXN0aW1hdGVzL1BJLyIpKQpQSTEgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUHJvamVjdEltcGxpY2l0UEQxLmNzdiIpClBJMiA8LSByZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNQcm9qZWN0SW1wbGljaXRQRDIuY3N2IikKClBJMSR0aW1lIDwtICJUMSIKUEkyJHRpbWUgPC0gIlQyIgpQSTEkc3ViSUQgPC0gMTpucm93KFBJMSkKUEkyJHN1YklEIDwtIDE6bnJvdyhQSTIpClAuUEkgPC0gcmJpbmQoUEkxLCBQSTIpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9HYXdyb25za2kvIikpCkdhdzEgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUERHYXdyb25za2kxLmNzdiIpCkdhdzIgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUERHYXdyb25za2kyLmNzdiIpCgpHYXcxJHRpbWUgPC0gIlQxIgpHYXcyJHRpbWUgPC0gIlQyIgpHYXcxJHN1YklEIDwtIDE6bnJvdyhHYXcxKQpHYXcyJHN1YklEIDwtIDE6bnJvdyhHYXcyKQpQLkdhdyA8LSByYmluZChHYXcxLCBHYXcyKQoKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvRm9yc2NoZXIvIikpCkZvcjE8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0ZvcnNjaGVyUEQxLmNzdiIsIGhlYWRlciA9IFQpCkZvcjI8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0ZvcnNjaGVyUEQyLmNzdiIsIGhlYWRlciA9IFQpCgpGb3IxJHRpbWUgPC0gIlQxIgpGb3IyJHRpbWUgPC0gIlQyIgpGb3IxJHN1YklEIDwtIDE6bnJvdyhGb3IxKQpGb3IyJHN1YklEIDwtIDE6bnJvdyhGb3IyKQpQLkZvciA8LSByYmluZChGb3IxLCBGb3IyKQoKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvTGFpMS8iKSkKTGFpMTE8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0xhaVN0dWR5MVBEMS5jc3YiLCBoZWFkZXIgPSBUKQpMYWkxMjwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzTGFpU3R1ZHkxUEQyLmNzdiIsIGhlYWRlciA9IFQpCgpMYWkxMSR0aW1lIDwtICJUMSIKTGFpMTIkdGltZSA8LSAiVDIiCkxhaTExJHN1YklEIDwtIDE6bnJvdyhMYWkxMSkKTGFpMTIkc3ViSUQgPC0gMTpucm93KExhaTEyKQpQLkxhaTEgPC0gcmJpbmQoTGFpMTEsIExhaTEyKQoKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvTGFpMi8iKSkKTGFpMjE8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0xhaVN0dWR5MlBEMS5jc3YiLCBoZWFkZXIgPSBUKQpMYWkyMjwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzTGFpU3R1ZHkyUEQyLmNzdiIsIGhlYWRlciA9IFQpCgpMYWkyMSR0aW1lIDwtICJUMSIKTGFpMjIkdGltZSA8LSAiVDIiCkxhaTIxJHN1YklEIDwtIDE6bnJvdyhMYWkyMSkKTGFpMjIkc3ViSUQgPC0gMTpucm93KExhaTIyKQpQLkxhaTIgPC0gcmJpbmQoTGFpMjEsTGFpMjIpCgpjb2xuYW1lcyhQLkNhbClbMV0gPC0gInN1YklEIgpQLkNhbCA8LSBjYmluZChQLkNhbCwgU3R1ZHkgPSAiQ2FsYW5jaGluaSIpCmNvbG5hbWVzKFAuUEkpWzFdIDwtICJzdWJJRCIKUC5QSSA8LSBjYmluZChQLlBJLCBTdHVkeSA9ICJQSSIpCmNvbG5hbWVzKFAuR2F3KVsxXSA8LSAic3ViSUQiClAuR2F3IDwtIGNiaW5kKFAuR2F3LCBTdHVkeSA9ICJHYXdyb25za2kiKQpjb2xuYW1lcyhQLkZvcilbMV0gPC0gInN1YklEIgpQLkZvciA8LSBjYmluZChQLkZvciwgU3R1ZHkgPSAiRm9yc2NoZXIiKQpjb2xuYW1lcyhQLkxhaTEpWzFdIDwtICJzdWJJRCIKUC5MYWkxIDwtIGNiaW5kKFAuTGFpMSwgU3R1ZHkgPSAiTGFpIDEiKQpjb2xuYW1lcyhQLkxhaTIpWzFdIDwtICJzdWJJRCIKUC5MYWkyIDwtIGNiaW5kKFAuTGFpMiwgU3R1ZHkgPSAiTGFpIDIiKQoKUEQub3JpZyA8LSByYmluZChQLkNhbCxQLlBJLFAuR2F3LFAuRm9yLFAuTGFpMSxQLkxhaTIpClBELm9yaWdbMV0gPC0gTlVMTApgYGAKCmBgYHtyfQoKY29sbmFtZXMoUEQucmVjb3ZzKVsyOiAobmNvbChQRC5yZWNvdnMpLTIpIF0gPC0gcGFzdGUoY29sbmFtZXMoUEQucmVjb3ZzKVsyOiAobmNvbChQRC5yZWNvdnMpLTIpIF0sIlIiLHNlcD0iXyIpCmNvbG5hbWVzKFBELm9yaWcpWzE6IChuY29sKFBELm9yaWcpLTMpIF0gPC0gcGFzdGUoY29sbmFtZXMoUEQub3JpZylbMTogKG5jb2woUEQub3JpZyktMykgXSwiTyIsc2VwPSJfIikKUEQub3JpZyA8LSBQRC5vcmlnW29yZGVyKFBELm9yaWckU3R1ZHksIFBELm9yaWckdGltZSksXQpQRC5yZWNvdnMgPC0gUEQucmVjb3ZzW29yZGVyKFBELnJlY292cyRTdHVkeSwgUEQucmVjb3ZzJHRpbWUpLF0KCiNQRC5vcmlnLnJlY292cyA8LSBjYmluZChQRC5vcmlnLFBELnJlY292cykKUEQub3JpZy5yZWNvdnMgPC0gbWVyZ2UoUEQub3JpZywgUEQucmVjb3ZzLCBieSA9IGMoInN1YklEIiwiU3R1ZHkiLCJ0aW1lIikpCgpQRC5vcmlnLnJlY292cyRTdHVkeVtQRC5vcmlnLnJlY292cyRTdHVkeT09IlBJIl08LSJQcm9qZWN0IEltcGxpY2l0LCAyMDIwIgpQRC5vcmlnLnJlY292cyRTdHVkeVtQRC5vcmlnLnJlY292cyRTdHVkeT09IkNhbGFuY2hpbmkiXTwtIldpbHNvbiAmIENhbGFuY2hpbmksIDIwMjIiClBELm9yaWcucmVjb3ZzJFN0dWR5W1BELm9yaWcucmVjb3ZzJFN0dWR5PT0iTGFpIDEiXTwtIkxhaSBldCBhbC4sIDIwMTYgKFN0dWR5IDEpICAiClBELm9yaWcucmVjb3ZzJFN0dWR5W1BELm9yaWcucmVjb3ZzJFN0dWR5PT0iTGFpIDIiXTwtIkxhaSBldCBhbC4sIDIwMTYgKFN0dWR5IDIpICAiClBELm9yaWcucmVjb3ZzJFN0dWR5W1BELm9yaWcucmVjb3ZzJFN0dWR5PT0iR2F3cm9uc2tpIl08LSJHYXdyb25za2kgZXQgYWwuLCAyMDE3IgpQRC5vcmlnLnJlY292cyRTdHVkeVtQRC5vcmlnLnJlY292cyRTdHVkeT09IkZvcnNjaGVyIl08LSJGb3JzY2hlciBldCBhbC4sIDIwMTciCmBgYAoKCiMgUmVjb3ZlcnkKCiMjIFBEIE1vZGVsCgojIyMgQXV0b21hdGljIEJsYWNrCgpgYGB7cn0KQWJTY2F0dGVyIDwtIGdncGxvdChQRC5vcmlnLnJlY292cywgYWVzKHg9QWIxX08sIHk9QWIxX1IsIGNvbG9yPVN0dWR5LCBzaGFwZT10aW1lKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkF1dG9tYXRpYyBCbGFjayIsCiAgICAgICB4PSJPcmlnaW5hbCIsIHkgPSAiUmVjb3ZlcmVkIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpICsKICBqdG9vbHM6OnRoZW1lX2FwYSgpCgpBYlNjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkFiU2NhdHRlclJFQy5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQWJTY2F0dGVyUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIyBBdXRvbWF0aWMgV2hpdGUKCmBgYHtyfQpBd1NjYXR0ZXIgPC0gZ2dwbG90KFBELm9yaWcucmVjb3ZzLCBhZXMoeD1BdzFfTywgeT1BdzFfUiwgY29sb3I9U3R1ZHksIHNoYXBlPXRpbWUpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMikrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1UUlVFLAogICAgICAgICAgICAgY29sb3I9ImRhcmtncmV5IixhbHBoYT0xKSAgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkF1dG9tYXRpYyBXaGl0ZSIsCiAgICAgICB4PSJPcmlnaW5hbCIsIHkgPSAiUmVjb3ZlcmVkIikgKyBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoYWxwaGEgPSAxKSkpICsKICBqdG9vbHM6OnRoZW1lX2FwYSgpCkF3U2NhdHRlcgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQXdTY2F0dGVyUkVDLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJBd1NjYXR0ZXJSRUMudGlmZiIpLGRwaT02MDApCmBgYAoKIyMjIENvbnRyb2wgR29vZAoKYGBge3J9CkNwU2NhdHRlciA8LSBnZ3Bsb3QoUEQub3JpZy5yZWNvdnMsIGFlcyh4PUNwMV9PLCB5PUNwMV9SLCBjb2xvcj1TdHVkeSwgc2hhcGU9dGltZSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICAgKyBnZW9tX2FibGluZShpbnRlcmNlcHQgPSAwLCBzbG9wZSA9IDEpICsgeWxpbSgwLDEpICsgeGxpbSgwLDEpICsgbGFicyh0aXRsZT0iQ29udHJvbCBHb29kIiwKICAgICAgIHg9Ik9yaWdpbmFsIiwgeSA9ICJSZWNvdmVyZWQiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKQ3BTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJDcFNjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkF3U2NhdHRlclJFQy50aWZmIiksZHBpPTYwMCkKYGBgCgojIyMgQ29udHJvbCBCYWQKCmBgYHtyfQpDdVNjYXR0ZXIgPC0gZ2dwbG90KFBELm9yaWcucmVjb3ZzLCBhZXMoeD1DdTFfTywgeT1DdTFfUiwgY29sb3I9U3R1ZHksIHNoYXBlPXRpbWUpKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAuMikrCiAgZ2VvbV9zbW9vdGgobWV0aG9kPWxtLCBzZT1UUlVFLAogICAgICAgICAgICAgY29sb3I9ImRhcmtncmV5IixhbHBoYT0xKSAgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkNvbnRyb2wgQmFkIiwKICAgICAgIHg9Ik9yaWdpbmFsIiwgeSA9ICJSZWNvdmVyZWQiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKQ3VTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJDdVNjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkN1U2NhdHRlclJFQy50aWZmIiksZHBpPTYwMCkKYGBgCgojIyMgQ29udHJvbCBXaGl0ZQoKYGBge3J9CkN3U2NhdHRlciA8LSBnZ3Bsb3QoUEQub3JpZy5yZWNvdnMsIGFlcyh4PUN3MV9PLCB5PUN3MV9SLCBjb2xvcj1TdHVkeSwgc2hhcGU9dGltZSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJDb250cm9sIFdoaXRlIiwKICAgICAgIHg9Ik9yaWdpbmFsIiwgeSA9ICJSZWNvdmVyZWQiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKQ3dTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJDd1NjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkN3U2NhdHRlclJFQy50aWZmIiksZHBpPTYwMCkKYGBgCgojIyMgQ29udHJvbCBCbGFjawoKYGBge3J9CkNiU2NhdHRlciA8LSBnZ3Bsb3QoUEQub3JpZy5yZWNvdnMsIGFlcyh4PUNiMV9PLCB5PUNiMV9SLCBjb2xvcj1TdHVkeSwgc2hhcGU9dGltZSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJDb250cm9sIEJsYWNrIiwKICAgICAgIHg9Ik9yaWdpbmFsIiwgeSA9ICJSZWNvdmVyZWQiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKQ2JTY2F0dGVyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJDYlNjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkNiU2NhdHRlclJFQy50aWZmIiksZHBpPTYwMCkKYGBgCgojIyMgUGFuZWwKCmBgYHtyfQpsaWJyYXJ5KGdncHVicikKUERQYW5lbDEgPC0gZ2dhcnJhbmdlKEF3U2NhdHRlciwgQWJTY2F0dGVyLCBDdVNjYXR0ZXIsIENwU2NhdHRlciwgQ2JTY2F0dGVyLCBDd1NjYXR0ZXIsCiAgICAgICAgICBuY29sID0gMywgbnJvdyA9IDIsIGNvbW1vbi5sZWdlbmQgPSBUKQpQRFBhbmVsMQoKcmVxdWlyZShncmlkKSAgICMgZm9yIHRoZSB0ZXh0R3JvYigpIGZ1bmN0aW9uCgpQRFBhbmVsMiA8LSBnZ2FycmFuZ2UoQXdTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICsgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIEFiU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgQ3VTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICsgcnJlbW92ZSgieWxhYiIpICsgcnJlbW92ZSgieGxhYiIpLAogICAgICAgICAgICAgICAgICAgICAgICBDcFNjYXR0ZXIgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgKyBycmVtb3ZlKCJ5bGFiIikgKyBycmVtb3ZlKCJ4bGFiIiksCiAgICAgICAgICAgICAgICAgICAgICAgIENiU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgQ3dTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICsgcnJlbW92ZSgieWxhYiIpICsgcnJlbW92ZSgieGxhYiIpLAogICAgICAgICAgbmNvbCA9IDMsIG5yb3cgPSAyLCBjb21tb24ubGVnZW5kID0gVCwgbGFiZWxzID0gTlVMTCwgbGVnZW5kID0gYygiYm90dG9tIiksCiAgICAgICAgICBhbGlnbiA9ICJodiIsIAogICAgICAgICAgICAgICAgICAgIGZvbnQubGFiZWwgPSBsaXN0KHNpemUgPSAxMCwgY29sb3IgPSAiYmxhY2siLCBmYWNlID0gImJvbGQiLCBmYW1pbHkgPSBOVUxMLCBwb3NpdGlvbiA9ICJ0b3AiKSkKClBEUGFuZWwyIDwtIGFubm90YXRlX2ZpZ3VyZShQRFBhbmVsMiwgbGVmdCA9IHRleHRHcm9iKCJSZWNvdmVyZWQiLCByb3QgPSA5MCwgdmp1c3QgPSAxLCBoanVzdCA9IDAsIGdwID0gZ3BhcihjZXggPSAxKSksCiAgICAgICAgICAgICAgICAgICAgYm90dG9tID0gdGV4dEdyb2IoIk9yaWdpbmFsIiwgdmp1c3QgPSAtNi41LCBncCA9IGdwYXIoY2V4ID0gMSkpKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9IGMoMCwtMSkpClBEUGFuZWwyCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJQRFBhbmVsUkVDLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJQRFBhbmVsUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIFF1YWQgTW9kZWwKCiMgUmVjb3ZlcnkKCmBgYHtyfQpzZXR3ZChwYXN0ZTAoIi9Wb2x1bWVzL1Jlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9SZWNvdmVyeS9SZWNvdmVyZWRQYXJhbXMvUXVhZC8iKSkKdGltZXM8LWMoIlRpbWUxIiwiVGltZTIiKQoKYWxscmVjb3ZzIDwtIGFzLmRhdGEuZnJhbWUobWF0cml4KG5jb2w9MTQsbnJvdz0wKSkKClF1YWRkaXJzIDwtIGxpc3QuZGlycyhwYXRoID0gIi4iLCBmdWxsLm5hbWVzID0gVFJVRSwgcmVjdXJzaXZlID0gVFJVRSlbLTFdCmZvcihkIGluIFF1YWRkaXJzKXsKICBmb3IodGkgaW4gdGltZXMpewogICAgY3VyRmlsZXMgPC0gbGlzdC5maWxlcyhwYXRoPWQscGF0dGVybj0iXFwuY3N2JCIpCiAgICBpZDwtZ3JlcCh0aSxjdXJGaWxlcykKICAgIG91dHB1dDwtcmVhZC5jc3YocGFzdGUwKGQsIi8iLGN1ckZpbGVzW2lkXSkpCiAgICBuYW1lPC1nc3ViKCIuLyIsIiIsZCkKICAgIG5hbWU8LWdzdWIoIiAiLCIiLG5hbWUpCiAgICAKICAgIGlmKHRpPT0iVGltZTEiKXsKICAgICAgI2NvbG5hbWVzKG91dHB1dCkgPC0gcGFzdGUoY29sbmFtZXMob3V0cHV0KSwiVDEiLHNlcD0iXyIpCiAgICAgIG91dHB1dCR0aW1lIDwtICJUMSIKICAgIH1lbHNlIGlmKHRpPT0iVGltZTIiKXsKICAgICAgI2NvbG5hbWVzKG91dHB1dCkgPC0gcGFzdGUoY29sbmFtZXMob3V0cHV0KSwiVDIiLHNlcD0iXyIpCiAgICAgIG91dHB1dCR0aW1lIDwtICJUMiIKICAgIH0KICAgIAogICAgYXNzaWduKHBhc3RlMChuYW1lLCIuUXVhZC5SZWNvdi4iLHRpKSxvdXRwdXQpCiAgfQogIGRmIDwtIHJiaW5kKGdldChwYXN0ZTAobmFtZSwiLlF1YWQuUmVjb3YuVGltZTEiKSksZ2V0KHBhc3RlMChuYW1lLCIuUXVhZC5SZWNvdi5UaW1lMiIpKSkKICBhc3NpZ24ocGFzdGUwKG5hbWUsIi5RdWFkLlJlY292IiksZGYpCiAgYWxscmVjb3ZzIDwtIHJiaW5kKGFsbHJlY292cyxjYmluZChkZixTdHVkeT1uYW1lKSkKfQoKCmFsbHJlY292cyRTdHVkeSA8LSBnc3ViKCJMYWkxIiwgIkxhaSAxIiwgYWxscmVjb3ZzJFN0dWR5KQphbGxyZWNvdnMkU3R1ZHkgPC0gZ3N1YigiTGFpMiIsICJMYWkgMiIsIGFsbHJlY292cyRTdHVkeSkKUXVhZC5yZWNvdnMgPC0gYWxscmVjb3ZzClF1YWQucmVjb3ZzIDwtIGRwbHlyOjpyZW5hbWUoUXVhZC5yZWNvdnMsIHN1YklEPVgpCgp0YXBwbHkoUXVhZC5yZWNvdnMkQUNiYjEsIFF1YWQucmVjb3ZzJFN0dWR5LCBmdW5jdGlvbih4KSBsZW5ndGgoeCkpCmBgYAoKYGBge3J9CnBhdGggPC0gIi9Wb2x1bWVzLyIKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvVUNSLyIpKQpDYWwxIDwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUXVhZFVDUjEuY3N2IiwgaGVhZGVyID0gVCkKQ2FsMiA8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1F1YWRVQ1IyLmNzdiIsIGhlYWRlciA9IFQpCgpDYWwxJHRpbWUgPC0gIlQxIgpDYWwyJHRpbWUgPC0gIlQyIgpDYWwxJHN1YklEIDwtIDE6bnJvdyhDYWwxKQpDYWwyJHN1YklEIDwtIDE6bnJvdyhDYWwyKQpQLkNhbCA8LSByYmluZChDYWwxLCBDYWwyKQoKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvUEkvIikpClBJMSA8LSByZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNRdWFkUHJvamVjdEltcGxpY2l0MS5jc3YiKQpQSTIgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUXVhZFByb2plY3RJbXBsaWNpdDIuY3N2IikKClBJMSR0aW1lIDwtICJUMSIKUEkyJHRpbWUgPC0gIlQyIgpQSTEkc3ViSUQgPC0gMTpucm93KFBJMSkKUEkyJHN1YklEIDwtIDE6bnJvdyhQSTIpClAuUEkgPC0gcmJpbmQoUEkxLCBQSTIpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9HYXdyb25za2kvIikpCkdhdzEgPC0gcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzUXVhZEdhd3JvbnNraTEuY3N2IikKR2F3MiA8LSByZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNRdWFkR2F3cm9uc2tpMi5jc3YiKQoKR2F3MSR0aW1lIDwtICJUMSIKR2F3MiR0aW1lIDwtICJUMiIKR2F3MSRzdWJJRCA8LSAxOm5yb3coR2F3MSkKR2F3MiRzdWJJRCA8LSAxOm5yb3coR2F3MikKUC5HYXcgPC0gcmJpbmQoR2F3MSwgR2F3MikKCnNldHdkKHBhc3RlMChwYXRoLCJSZXNlYXJjaCBQcm9qZWN0L0lBVF9SZXRlc3QvRXN0aW1hdGVzL0ZvcnNjaGVyLyIpKQpGb3IxPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNRdWFkRm9yc2NoZXIxLmNzdiIsIGhlYWRlciA9IFQpCkZvcjI8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc1F1YWRGb3JzY2hlcjIuY3N2IiwgaGVhZGVyID0gVCkKCkZvcjEkdGltZSA8LSAiVDEiCkZvcjIkdGltZSA8LSAiVDIiCkZvcjEkc3ViSUQgPC0gMTpucm93KEZvcjEpCkZvcjIkc3ViSUQgPC0gMTpucm93KEZvcjIpClAuRm9yIDwtIHJiaW5kKEZvcjEsIEZvcjIpCgpzZXR3ZChwYXN0ZTAocGF0aCwiUmVzZWFyY2ggUHJvamVjdC9JQVRfUmV0ZXN0L0VzdGltYXRlcy9MYWkxLyIpKQpMYWkxMTwtcmVhZC5jc3YoIkluZGl2aWR1YWxQYXJhbWV0ZXJzTGFpU3R1ZHkxUXVhZDEuY3N2IiwgaGVhZGVyID0gVCkKTGFpMTI8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0xhaVN0dWR5MVF1YWQyLmNzdiIsIGhlYWRlciA9IFQpCgpMYWkxMSR0aW1lIDwtICJUMSIKTGFpMTIkdGltZSA8LSAiVDIiCkxhaTExJHN1YklEIDwtIDE6bnJvdyhMYWkxMSkKTGFpMTIkc3ViSUQgPC0gMTpucm93KExhaTEyKQpQLkxhaTEgPC0gcmJpbmQoTGFpMTEsIExhaTEyKQoKc2V0d2QocGFzdGUwKHBhdGgsIlJlc2VhcmNoIFByb2plY3QvSUFUX1JldGVzdC9Fc3RpbWF0ZXMvTGFpMi8iKSkKTGFpMjE8LXJlYWQuY3N2KCJJbmRpdmlkdWFsUGFyYW1ldGVyc0xhaVN0dWR5MlF1YWQxLmNzdiIsIGhlYWRlciA9IFQpCkxhaTIyPC1yZWFkLmNzdigiSW5kaXZpZHVhbFBhcmFtZXRlcnNMYWlTdHVkeTJRdWFkMi5jc3YiLCBoZWFkZXIgPSBUKQoKTGFpMjEkdGltZSA8LSAiVDEiCkxhaTIyJHRpbWUgPC0gIlQyIgpMYWkyMSRzdWJJRCA8LSAxOm5yb3coTGFpMjEpCkxhaTIyJHN1YklEIDwtIDE6bnJvdyhMYWkyMikKUC5MYWkyIDwtIHJiaW5kKExhaTIxLExhaTIyKQoKY29sbmFtZXMoUC5DYWwpWzFdIDwtICJzdWJJRCIKUC5DYWwgPC0gY2JpbmQoUC5DYWwsIFN0dWR5ID0gIkNhbGFuY2hpbmkiKQpjb2xuYW1lcyhQLlBJKVsxXSA8LSAic3ViSUQiClAuUEkgPC0gY2JpbmQoUC5QSSwgU3R1ZHkgPSAiUEkiKQpjb2xuYW1lcyhQLkdhdylbMV0gPC0gInN1YklEIgpQLkdhdyA8LSBjYmluZChQLkdhdywgU3R1ZHkgPSAiR2F3cm9uc2tpIikKY29sbmFtZXMoUC5Gb3IpWzFdIDwtICJzdWJJRCIKUC5Gb3IgPC0gY2JpbmQoUC5Gb3IsIFN0dWR5ID0gIkZvcnNjaGVyIikKY29sbmFtZXMoUC5MYWkxKVsxXSA8LSAic3ViSUQiClAuTGFpMSA8LSBjYmluZChQLkxhaTEsIFN0dWR5ID0gIkxhaSAxIikKY29sbmFtZXMoUC5MYWkyKVsxXSA8LSAic3ViSUQiClAuTGFpMiA8LSBjYmluZChQLkxhaTIsIFN0dWR5ID0gIkxhaSAyIikKClF1YWQub3JpZyA8LSByYmluZChQLkNhbCxQLlBJLFAuR2F3LFAuRm9yLFAuTGFpMSxQLkxhaTIpClF1YWQub3JpZ1sxXSA8LSBOVUxMCmBgYAoKYGBge3J9CmNvbG5hbWVzKFF1YWQucmVjb3ZzKVsyOiAobmNvbChRdWFkLnJlY292cyktMikgXSA8LSBwYXN0ZShjb2xuYW1lcyhRdWFkLnJlY292cylbMjogKG5jb2woUXVhZC5yZWNvdnMpLTIpIF0sIlIiLHNlcD0iXyIpCmNvbG5hbWVzKFF1YWQub3JpZylbMTogKG5jb2woUXVhZC5vcmlnKS0zKSBdIDwtIHBhc3RlKGNvbG5hbWVzKFF1YWQub3JpZylbMTogKG5jb2woUXVhZC5vcmlnKS0zKSBdLCJPIixzZXA9Il8iKQpRdWFkLm9yaWcgPC0gUXVhZC5vcmlnW29yZGVyKFF1YWQub3JpZyRTdHVkeSwgUXVhZC5vcmlnJHRpbWUpLF0KUXVhZC5yZWNvdnMgPC0gUXVhZC5yZWNvdnNbb3JkZXIoUXVhZC5yZWNvdnMkU3R1ZHksIFF1YWQucmVjb3ZzJHRpbWUpLF0KCiNRdWFkLm9yaWcucmVjb3ZzIDwtIGNiaW5kKFF1YWQub3JpZyxRdWFkLnJlY292cykKUXVhZC5vcmlnLnJlY292cyA8LSBtZXJnZShRdWFkLm9yaWcsIFF1YWQucmVjb3ZzLCBieSA9IGMoInN1YklEIiwiU3R1ZHkiLCJ0aW1lIikpCgpRdWFkLm9yaWcucmVjb3ZzJFN0dWR5W1F1YWQub3JpZy5yZWNvdnMkU3R1ZHk9PSJQSSJdPC0iUHJvamVjdCBJbXBsaWNpdCwgMjAyMCIKUXVhZC5vcmlnLnJlY292cyRTdHVkeVtRdWFkLm9yaWcucmVjb3ZzJFN0dWR5PT0iQ2FsYW5jaGluaSJdPC0iV2lsc29uICYgQ2FsYW5jaGluaSwgMjAyMiIKUXVhZC5vcmlnLnJlY292cyRTdHVkeVtRdWFkLm9yaWcucmVjb3ZzJFN0dWR5PT0iTGFpIDEiXTwtIkxhaSBldCBhbC4sIDIwMTYgKFN0dWR5IDEpICAiClF1YWQub3JpZy5yZWNvdnMkU3R1ZHlbUXVhZC5vcmlnLnJlY292cyRTdHVkeT09IkxhaSAyIl08LSJMYWkgZXQgYWwuLCAyMDE2IChTdHVkeSAyKSAgIgpRdWFkLm9yaWcucmVjb3ZzJFN0dWR5W1F1YWQub3JpZy5yZWNvdnMkU3R1ZHk9PSJHYXdyb25za2kiXTwtIkdhd3JvbnNraSBldCBhbC4sIDIwMTciClF1YWQub3JpZy5yZWNvdnMkU3R1ZHlbUXVhZC5vcmlnLnJlY292cyRTdHVkeT09IkZvcnNjaGVyIl08LSJGb3JzY2hlciBldCBhbC4sIDIwMTciCmBgYAoKIyMgUXVhZCBNb2RlbAoKIyMjIEFzc29jaWF0ZSBCbGFjay1CYWQKCmBgYHtyfQpBQ2JiU2NhdHRlciA8LSBnZ3Bsb3QoUXVhZC5vcmlnLnJlY292cywgYWVzKHg9QUNiYjFfTywgeT1BQ2JiMV9SLCBjb2xvcj1TdHVkeSwgc2hhcGU9dGltZSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJBc3NvY2lhdGlvbiBCbGFjay1CYWQiLAogICAgICAgeD0iT3JpZ2luYWwiLCB5ID0gIlJlY292ZXJlZCIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpBQ2JiU2NhdHRlcgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQUNiYlNjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkFDYmJTY2F0dGVyUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIyBBc3NvY2lhdGUgV2hpdGUtR29vZAoKYGBge3J9CkFDd2dTY2F0dGVyIDwtIGdncGxvdChRdWFkLm9yaWcucmVjb3ZzLCBhZXMoeD1BQ3dnMV9PLCB5PUFDd2cxX1IsIGNvbG9yPVN0dWR5LCBzaGFwZT10aW1lKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9IkFzc29jaWF0aW9uIFdoaXRlLUdvb2QiLAogICAgICAgeD0iT3JpZ2luYWwiLCB5ID0gIlJlY292ZXJlZCIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpBQ3dnU2NhdHRlcgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiQUN3Z1NjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkFDd2dTY2F0dGVyUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIyBEZXRlY3Rpb24KCmBgYHtyfQpEU2NhdHRlciA8LSBnZ3Bsb3QoUXVhZC5vcmlnLnJlY292cywgYWVzKHg9RDFfTywgeT1EMV9SLCBjb2xvcj1TdHVkeSwgc2hhcGU9dGltZSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJEZXRlY3Rpb24iLAogICAgICAgeD0iT3JpZ2luYWwiLCB5ID0gIlJlY292ZXJlZCIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpEU2NhdHRlcgpnZ3NhdmUocGFzdGUwKHNhdmV0bywiRFNjYXR0ZXJSRUMuanBnIiksZHBpPTYwMCkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkRTY2F0dGVyUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIyBPdmVyY29taW5nIEJpYXMKCmBgYHtyfQpPQlNjYXR0ZXIgPC0gZ2dwbG90KFF1YWQub3JpZy5yZWNvdnMsIGFlcyh4PU9CMV9PLCB5PU9CMV9SLCBjb2xvcj1TdHVkeSwgc2hhcGU9dGltZSkpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IC4yKSsKICBnZW9tX3Ntb290aChtZXRob2Q9bG0sIHNlPVRSVUUsCiAgICAgICAgICAgICBjb2xvcj0iZGFya2dyZXkiLGFscGhhPTEpICArIGdlb21fYWJsaW5lKGludGVyY2VwdCA9IDAsIHNsb3BlID0gMSkgKyB5bGltKDAsMSkgKyB4bGltKDAsMSkgKyBsYWJzKHRpdGxlPSJPdmVyY29taW5nIEJpYXMiLAogICAgICAgeD0iT3JpZ2luYWwiLCB5ID0gIlJlY292ZXJlZCIpICsgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KGFscGhhID0gMSkpKSArCiAganRvb2xzOjp0aGVtZV9hcGEoKQpPQlNjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIk9CU2NhdHRlclJFQy5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiT0JTY2F0dGVyUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMjIyBHdWVzc2luZwoKYGBge3J9CkdTY2F0dGVyIDwtIGdncGxvdChRdWFkLm9yaWcucmVjb3ZzLCBhZXMoeD1HMV9PLCB5PUcxX1IsIGNvbG9yPVN0dWR5LCBzaGFwZT10aW1lKSkgKyAKICBnZW9tX3BvaW50KGFscGhhID0gLjIpKwogIGdlb21fc21vb3RoKG1ldGhvZD1sbSwgc2U9VFJVRSwKICAgICAgICAgICAgIGNvbG9yPSJkYXJrZ3JleSIsYWxwaGE9MSkgICsgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArIHlsaW0oMCwxKSArIHhsaW0oMCwxKSArIGxhYnModGl0bGU9Ikd1ZXNzaW5nIiwKICAgICAgIHg9Ik9yaWdpbmFsIiwgeSA9ICJSZWNvdmVyZWQiKSArIGd1aWRlcyhjb2xvdXIgPSBndWlkZV9sZWdlbmQob3ZlcnJpZGUuYWVzID0gbGlzdChhbHBoYSA9IDEpKSkgKwogIGp0b29sczo6dGhlbWVfYXBhKCkKR1NjYXR0ZXIKZ2dzYXZlKHBhc3RlMChzYXZldG8sIkdTY2F0dGVyLmpwZyIpLGRwaT02MDApCmdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJHU2NhdHRlci50aWZmIiksZHBpPTYwMCkKYGBgCgojIyMgUGFuZWwKCmBgYHtyfQpsaWJyYXJ5KGdncHVicikKUXVhZFBhbmVsMSA8LSBnZ2FycmFuZ2UoQUN3Z1NjYXR0ZXIsIEFDYmJTY2F0dGVyLCBEU2NhdHRlciwgT0JTY2F0dGVyLCBHU2NhdHRlciwKICAgICAgICAgIG5jb2wgPSAzLCBucm93ID0gMiwgY29tbW9uLmxlZ2VuZCA9IFQpClF1YWRQYW5lbDEKCnJlcXVpcmUoZ3JpZCkgICAjIGZvciB0aGUgdGV4dEdyb2IoKSBmdW5jdGlvbgoKUXVhZFBhbmVsMiA8LSBnZ2FycmFuZ2UoQUN3Z1NjYXR0ZXIgICsgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkgICsgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgIEFDYmJTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICsgcnJlbW92ZSgieWxhYiIpICsgcnJlbW92ZSgieGxhYiIpLAogICAgICAgICAgICAgICAgICAgICAgICBEU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgT0JTY2F0dGVyICArIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpICsgcnJlbW92ZSgieWxhYiIpICsgcnJlbW92ZSgieGxhYiIpLAogICAgICAgICAgICAgICAgICAgICAgICBHU2NhdHRlciAgKyB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKSArIHJyZW1vdmUoInlsYWIiKSArIHJyZW1vdmUoInhsYWIiKSwKICAgICAgICAgIG5jb2wgPSAzLCBucm93ID0gMiwgY29tbW9uLmxlZ2VuZCA9IFQsIGxhYmVscyA9IE5VTEwsIGxlZ2VuZCA9ICJib3R0b20iLAogICAgICAgICAgYWxpZ24gPSAiaHYiLCAKICAgICAgICAgICAgICAgICAgICBmb250LmxhYmVsID0gbGlzdChzaXplID0gMTAsIGNvbG9yID0gImJsYWNrIiwgZmFjZSA9ICJib2xkIiwgZmFtaWx5ID0gTlVMTCwgcG9zaXRpb24gPSAidG9wIikpClF1YWRQYW5lbDIKCmFubm90YXRlX2ZpZ3VyZShRdWFkUGFuZWwyLCBsZWZ0ID0gdGV4dEdyb2IoIlJlY292ZXJlZCIsIHJvdCA9IDkwLCB2anVzdCA9IDEsIGhqdXN0ID0gMCwgZ3AgPSBncGFyKGNleCA9IDEpKSwKICAgICAgICAgICAgICAgICAgICBib3R0b20gPSB0ZXh0R3JvYigiT3JpZ2luYWwiLCB2anVzdCA9IC02LjUsIGdwID0gZ3BhcihjZXggPSAxKSkpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gYygwLC0xKSkKZ2dzYXZlKHBhc3RlMChzYXZldG8sIlF1YWRQYW5lbFJFQy5qcGciKSxkcGk9NjAwKQpnZ3NhdmUocGFzdGUwKHNhdmV0bywiUXVhZFBhbmVsUkVDLnRpZmYiKSxkcGk9NjAwKQpgYGAKCiMgUmVjb3ZlcnkgTWV0YS1BbmFseXNpcwoKIyMgUXVhZAoKCmBgYHtyfQpkdCA8LSByZWFkLmNzdigifi9Eb2N1bWVudHMvR2l0SHViL01QVC1SZWxpYWJpbGl0eS9SZWNvdmVyeS9vdXRwdXQvY29tYlF1YWRfUmVjb3ZlcnlfRGYuY3N2IilbMjo3XQpkdCRpZCA8LSB1bmxpc3QobGFwcGx5KDE6NSwgZnVuY3Rpb24oeCkgcmVwKHgsdGltZXM9MTMpKSkKCmR0JFBhcmFtW2R0JFBhcmFtPT0iRCJdPC0iRGV0ZWN0aW9uIgpkdCRQYXJhbVtkdCRQYXJhbT09Ik9CIl08LSJPdmVyY29taW5nIEJpYXMiCmR0JFBhcmFtW2R0JFBhcmFtPT0iQUNiYiJdPC0iQXNzb2NpYXRpb24gQmxhY2stQmFkIgpkdCRQYXJhbVtkdCRQYXJhbT09IkFDd2ciXTwtIkFzc29jaWF0aW9uIFdoaXRlLUdvb2QiCmR0JFBhcmFtW2R0JFBhcmFtPT0iRyJdPC0iR3Vlc3NpbmciCgpkdCRQYXJhbVtkdCRQYXJhbT09IlBJIl08LSJQcm9qZWN0IEltcGxpY2l0LCAyMDIwIgpkdCRQYXJhbVtkdCRQYXJhbT09IkNhbGFuY2hpbmkiXTwtIldpbHNvbiAmIENhbGFuY2hpbmksIDIwMjIiCmR0JFBhcmFtW2R0JFBhcmFtPT0iTGFpMSJdPC0iTGFpIGV0IGFsLiwgMjAxNiAoU3R1ZHkgMSkgICIKZHQkUGFyYW1bZHQkUGFyYW09PSJMYWkyIl08LSJMYWkgZXQgYWwuLCAyMDE2IChTdHVkeSAyKSAgIgpkdCRQYXJhbVtkdCRQYXJhbT09Ikdhd3JvbnNraSJdPC0iR2F3cm9uc2tpIGV0IGFsLiwgMjAxNyIKZHQkUGFyYW1bZHQkUGFyYW09PSJGb3JzY2hlciJdPC0iRm9yc2NoZXIgZXQgYWwuLCAyMDE3IgoKIyBpbmRlbnQgdGhlIHN1Ymdyb3VwIGlmIHRoZXJlIGlzIGEgbnVtYmVyIGluIHRoZSBwbGFjZWJvIGNvbHVtbgpkdCRQYXJhbSA8LSBpZmVsc2UoZHQkdHlwZT09MCwgCiAgICAgICAgICAgICAgICAgICAgICBkdCRQYXJhbSwKICAgICAgICAgICAgICAgICAgICAgIHBhc3RlMCgiICIsIGR0JFBhcmFtKSkKCmR0JGAgYCA8LSBwYXN0ZShyZXAoIiAiLCAyMCksIGNvbGxhcHNlID0gIiAiKQpkdCRgUmVjb3ZlcnkgKDk1JSBDSSlgIDwtIGlmZWxzZShpcy5uYShkdCRSZWNvdiksICIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwcmludGYoIiUuMmYgWyUuMmYsICUuMmZdIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGR0JFJlY292LCBkdCRDSS5MQiwgZHQkQ0kuVUIpKQoKZHQyIDwtIHBpdm90X3dpZGVyKGR0LCBpZF9jb2xzID0gYygiUGFyYW0iLCJpZCIpLCAgbmFtZXNfZnJvbSA9IGMoVGltZSksIHZhbHVlc19mcm9tID0gYyhSZWNvdixDSS5MQixDSS5VQixgUmVjb3ZlcnkgKDk1JSBDSSlgKSApCmR0MiRgUmVjb3ZlcnkgWzk1JSBDSV1gIDwtIGlmZWxzZSghaXMubmEoZHQyJGBSZWNvdmVyeSAoOTUlIENJKV9NZXRhYCksIHBhc3RlMCgiICAgICAgICAgICAgICAgICAiLGR0MiRgUmVjb3ZlcnkgKDk1JSBDSSlfTWV0YWApLCBwYXN0ZTAoIlQxIDoiLCBwYXN0ZTAoZHQyJGBSZWNvdmVyeSAoOTUlIENJKV9UaW1lMWApLCAiIDsgIiwgIlQyOiAiLCBwYXN0ZTAoZHQyJGBSZWNvdmVyeSAoOTUlIENJKV9UaW1lMmApKSkKZHQyJGAgYCA8LSBwYXN0ZShyZXAoIiAiLCAyMCksIGNvbGxhcHNlID0gIiAiKQoKCmR0MzwtZHQyICU+JSBzZWxlY3QoUGFyYW0sUmVjb3ZfTWV0YToxMSwxNSwxNikKCmNvbG5hbWVzKGR0MylbY29sbmFtZXMoZHQzKT09IlBhcmFtIl0gPC0gIiAgICIKY29sbmFtZXMoZHQzKVtjb2xuYW1lcyhkdDMpPT0iUmVjb3ZlcnkgWzk1JSBDSV0iXSA8LSAiICAgICIKCmR0MyRzaXplX01ldGEgPC0gaWZlbHNlKGlzLm5hKGR0MyRSZWNvdl9NZXRhKSwgTkEsIDEuMikKZHQzJHNpemVfVDEgPC0gaWZlbHNlKGlzLm5hKGR0MyRSZWNvdl9UaW1lMSksIE5BLCAuNikKZHQzJHNpemVfVDIgPC0gaWZlbHNlKGlzLm5hKGR0MyRSZWNvdl9UaW1lMiksIE5BLCAuNikKCiMgU2V0LXVwIHRoZW1lCnRtIDwtIGZvcmVzdF90aGVtZSgKICAgICAgICAgICAgICAgICAgIGNpX3BjaCA9IGMoMTUsIDE2LCAxNyksCiAgICAgICAgICAgICAgICAgICBjaV9jb2wgPSBjKCJibGFjayIsInJlZCIsImJsdWUiKSwKICAgICAgICAgICAgICAgICAgIGNpX2x0eSA9IGMoICJzb2xpZCIsICJkYXNoZWQiLCAiZG90dGVkIiksCiAgICAgICAgICAgICAgICAgICMgZm9vdG5vdGVfY29sID0gImJsdWUiLAogICAgICAgICAgICAgICAgICAgbGVnZW5kX25hbWUgPSAiICIsCiAgICAgICAgICAgICAgICAgIGxlZ2VuZF9wb3NpdGlvbiA9ICJib3R0b20iLAogICAgICAgICAgICAgICAgICAgbGVnZW5kX3ZhbHVlID0gYygiTWV0YS1BbmFseXNpcyAiLCAiVGltZSAxICIsICJUaW1lIDIgIikpCgpsaWJyYXJ5KGZvcmVzdHBsb3RlcikKcCA8LSBmb3Jlc3QoCiAgZHQzW2MoMSwxMiwxMSldLAogICAgICAgICAgICBlc3QgPSBsaXN0KGR0MyRSZWNvdl9NZXRhLCBkdDMkUmVjb3ZfVGltZTEsIGR0MyRSZWNvdl9UaW1lMiksCiAgICAgICAgICAgIGxvd2VyID0gbGlzdChkdDMkQ0kuTEJfTWV0YSwgZHQzJENJLkxCX1RpbWUxLCBkdDMkQ0kuTEJfVGltZTIpLCAKICAgICAgICAgICAgdXBwZXIgPSBsaXN0KGR0MyRDSS5VQl9NZXRhLCBkdDMkQ0kuVUJfVGltZTEsIGR0MyRDSS5VQl9UaW1lMiksCiAgICAgICAgICAgIGNpX2NvbHVtbiA9IDIsCiAgICAgICAgICAgIHJlZl9saW5lID0gLjcsCiAgICAgICAgICAgIHhsaW0gPSBjKC0uMSwgMSksCiAgICAgICAgICAgIHRpY2tzX2F0ID0gYygwLCAuMiwgLjUsIC43LCAxKSwKICBzaXplcyA9IGxpc3QoZHQzJHNpemVfTWV0YSwgZHQzJHNpemVfVDEsIGR0MyRzaXplX1QyKSwKICB0aGVtZSA9IHRtCikKcGxvdChwKQoKbGlicmFyeShncmlkKQpwIDwtIGVkaXRfcGxvdChwLAogICAgICAgICAgICAgICByb3cgPSBzZXEoZnJvbT0xLHRvPW5yb3coZHQzKSxieT03KSwKICAgICAgICAgICAgICAgZ3AgPSBncGFyKGZvbnRmYWNlID0gYygiYm9sZCIsIml0YWxpYyIpCiAgICAgICAgICAgICAgICAgICAgICAgICApLCBjb2wgPSAxKQoKc3R1ZHlJbmRzIDwtIHNldGRpZmYoMTpucm93KGR0Myksc2VxKGZyb209MSx0bz1ucm93KGR0MyksYnk9NykpCnBhcmFtSW5kcyA8LSBzZXEoZnJvbT0xLHRvPW5yb3coZHQpLGJ5PTcpCgpwIDwtIGVkaXRfcGxvdChwLCByb3cgPSBzdHVkeUluZHMsIHdoaWNoID0gImJhY2tncm91bmQiLAogICAgICAgICAgICAgICBncCA9IGdwYXIoZmlsbCA9ICJ3aGl0ZSIpKQpwIDwtIGVkaXRfcGxvdChwLCByb3cgPSBwYXJhbUluZHMsIHdoaWNoID0gImJhY2tncm91bmQiLAogICAgICAgICAgICAgICBncCA9IGdwYXIoZmlsbCA9ICJncmV5IikpCgpgYGAKCmBgYHtyfQpwbmcoIn4vRGVza3RvcC9RdWFkX1JlY292Rm9yZXN0LnBuZyIsIHVuaXRzPSJpbiIsIHdpZHRoPTEwLCBoZWlnaHQ9MTUsIHJlcz0zMDApCnBsb3QocCkKZGV2Lm9mZigpCmBgYAoKYGBge3J9CiMgZ2dzYXZlIGZ1bmN0aW9uCmdncGxvdDI6Omdnc2F2ZShwYXN0ZTAoc2F2ZXRvLCJRdWFkX1JlY292Rm9yZXN0LnBuZyIpLAogICAgICAgICAgICAgICAgZHBpID0gMzAwLAogICAgICAgICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSAxNSwgdW5pdHMgPSAiaW4iLCBwbG90PXApCgpnZ3Bsb3QyOjpnZ3NhdmUocGFzdGUwKHNhdmV0bywiUXVhZF9SZWNvdkZvcmVzdC50aWZmIiksCiAgICAgICAgICAgICAgICBkcGkgPSAzMDAsCiAgICAgICAgICAgICAgICB3aWR0aCA9IDgsIGhlaWdodCA9IDE1LCB1bml0cyA9ICJpbiIsIHBsb3Q9cCkKYGBgCgoKYGBge3J9CmR0IDwtIHJlYWQuY3N2KCJ+L0RvY3VtZW50cy9HaXRIdWIvTVBULVJlbGlhYmlsaXR5L1JlY292ZXJ5L291dHB1dC9jb21iUERfUmVjb3ZlcnlfRGYuY3N2IilbMjo3XQpkdCRpZCA8LSB1bmxpc3QobGFwcGx5KDE6NiwgZnVuY3Rpb24oeCkgcmVwKHgsdGltZXM9MTMpKSkKCmR0JFBhcmFtW2R0JFBhcmFtPT0iQWIiXTwtIkF1dG9tYXRpYyBCbGFjayIKZHQkUGFyYW1bZHQkUGFyYW09PSJBdyJdPC0iQXV0b21hdGljIFdoaXRlIgpkdCRQYXJhbVtkdCRQYXJhbT09IkNiIl08LSJDb250cm9sIEJsYWNrIgpkdCRQYXJhbVtkdCRQYXJhbT09IkN3Il08LSJDb250cm9sIFdoaXRlIgpkdCRQYXJhbVtkdCRQYXJhbT09IkN1Il08LSJDb250cm9sIEJhZCIKZHQkUGFyYW1bZHQkUGFyYW09PSJDcCJdPC0iQ29udHJvbCBHb29kIgoKZHQkUGFyYW1bZHQkUGFyYW09PSJQSSJdPC0iUHJvamVjdCBJbXBsaWNpdCwgMjAyMCIKZHQkUGFyYW1bZHQkUGFyYW09PSJDYWxhbmNoaW5pIl08LSJXaWxzb24gJiBDYWxhbmNoaW5pLCAyMDIyIgpkdCRQYXJhbVtkdCRQYXJhbT09IkxhaTEiXTwtIkxhaSBldCBhbC4sIDIwMTYgKFN0dWR5IDEpICAiCmR0JFBhcmFtW2R0JFBhcmFtPT0iTGFpMiJdPC0iTGFpIGV0IGFsLiwgMjAxNiAoU3R1ZHkgMikgICIKZHQkUGFyYW1bZHQkUGFyYW09PSJHYXdyb25za2kiXTwtIkdhd3JvbnNraSBldCBhbC4sIDIwMTciCmR0JFBhcmFtW2R0JFBhcmFtPT0iRm9yc2NoZXIiXTwtIkZvcnNjaGVyIGV0IGFsLiwgMjAxNyIKCiMgaW5kZW50IHRoZSBzdWJncm91cCBpZiB0aGVyZSBpcyBhIG51bWJlciBpbiB0aGUgcGxhY2VibyBjb2x1bW4KZHQkUGFyYW0gPC0gaWZlbHNlKGR0JHR5cGU9PTAsIAogICAgICAgICAgICAgICAgICAgICAgZHQkUGFyYW0sCiAgICAgICAgICAgICAgICAgICAgICBwYXN0ZTAoIiAiLCBkdCRQYXJhbSkpCgpkdCRgIGAgPC0gcGFzdGUocmVwKCIgIiwgMjApLCBjb2xsYXBzZSA9ICIgIikKZHQkYFJlY292ZXJ5ICg5NSUgQ0kpYCA8LSBpZmVsc2UoaXMubmEoZHQkUmVjb3YpLCAiIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzcHJpbnRmKCIlLjJmIFslLjJmLCAlLjJmXSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkdCRSZWNvdiwgZHQkQ0kuTEIsIGR0JENJLlVCKSkKCmR0MiA8LSBwaXZvdF93aWRlcihkdCwgaWRfY29scyA9IGMoIlBhcmFtIiwiaWQiKSwgIG5hbWVzX2Zyb20gPSBjKFRpbWUpLCB2YWx1ZXNfZnJvbSA9IGMoUmVjb3YsQ0kuTEIsQ0kuVUIsYFJlY292ZXJ5ICg5NSUgQ0kpYCkgKQpkdDIkYFJlY292ZXJ5IFs5NSUgQ0ldYCA8LSBpZmVsc2UoIWlzLm5hKGR0MiRgUmVjb3ZlcnkgKDk1JSBDSSlfTWV0YWApLCBwYXN0ZTAoIiAgICAgICAgICAgICAgICAgIixkdDIkYFJlY292ZXJ5ICg5NSUgQ0kpX01ldGFgKSwgcGFzdGUwKCJUMSA6IiwgcGFzdGUwKGR0MiRgUmVjb3ZlcnkgKDk1JSBDSSlfVGltZTFgKSwgIiA7ICIsICJUMjogIiwgcGFzdGUwKGR0MiRgUmVjb3ZlcnkgKDk1JSBDSSlfVGltZTJgKSkpCmR0MiRgIGAgPC0gcGFzdGUocmVwKCIgIiwgMjApLCBjb2xsYXBzZSA9ICIgIikKCgpkdDM8LWR0MiAlPiUgc2VsZWN0KFBhcmFtLFJlY292X01ldGE6MTEsMTUsMTYpCgpjb2xuYW1lcyhkdDMpW2NvbG5hbWVzKGR0Myk9PSJQYXJhbSJdIDwtICIgICAiCmNvbG5hbWVzKGR0MylbY29sbmFtZXMoZHQzKT09IlJlY292ZXJ5IFs5NSUgQ0ldIl0gPC0gIiAgICAiCgpkdDMkc2l6ZV9NZXRhIDwtIGlmZWxzZShpcy5uYShkdDMkUmVjb3ZfTWV0YSksIE5BLCAxLjIpCmR0MyRzaXplX1QxIDwtIGlmZWxzZShpcy5uYShkdDMkUmVjb3ZfVGltZTEpLCBOQSwgLjYpCmR0MyRzaXplX1QyIDwtIGlmZWxzZShpcy5uYShkdDMkUmVjb3ZfVGltZTIpLCBOQSwgLjYpCgojIFNldC11cCB0aGVtZQp0bSA8LSBmb3Jlc3RfdGhlbWUoCiAgICAgICAgICAgICAgICAgICBjaV9wY2ggPSBjKDE1LCAxNiwgMTcpLAogICAgICAgICAgICAgICAgICAgY2lfY29sID0gYygiYmxhY2siLCJyZWQiLCJibHVlIiksCiAgICAgICAgICAgICAgICAgICBjaV9sdHkgPSBjKCAic29saWQiLCAiZGFzaGVkIiwgImRvdHRlZCIpLAogICAgICAgICAgICAgICAgICAjIGZvb3Rub3RlX2NvbCA9ICJibHVlIiwKICAgICAgICAgICAgICAgICAgIGxlZ2VuZF9uYW1lID0gIiAiLAogICAgICAgICAgICAgICAgICBsZWdlbmRfcG9zaXRpb24gPSAiYm90dG9tIiwKICAgICAgICAgICAgICAgICAgIGxlZ2VuZF92YWx1ZSA9IGMoIk1ldGEtQW5hbHlzaXMgIiwgIlRpbWUgMSAiLCAiVGltZSAyICIpKQoKbGlicmFyeShmb3Jlc3RwbG90ZXIpCnAgPC0gZm9yZXN0KAogIGR0M1tjKDEsMTIsMTEpXSwKICAgICAgICAgICAgZXN0ID0gbGlzdChkdDMkUmVjb3ZfTWV0YSwgZHQzJFJlY292X1RpbWUxLCBkdDMkUmVjb3ZfVGltZTIpLAogICAgICAgICAgICBsb3dlciA9IGxpc3QoZHQzJENJLkxCX01ldGEsIGR0MyRDSS5MQl9UaW1lMSwgZHQzJENJLkxCX1RpbWUyKSwgCiAgICAgICAgICAgIHVwcGVyID0gbGlzdChkdDMkQ0kuVUJfTWV0YSwgZHQzJENJLlVCX1RpbWUxLCBkdDMkQ0kuVUJfVGltZTIpLAogICAgICAgICAgICBjaV9jb2x1bW4gPSAyLAogICAgICAgICAgICByZWZfbGluZSA9IC43LAogICAgICAgICAgICB4bGltID0gYygtLjEsIDEpLAogICAgICAgICAgICB0aWNrc19hdCA9IGMoMCwgLjIsIC41LCAuNywgMSksCiAgc2l6ZXMgPSBsaXN0KGR0MyRzaXplX01ldGEsIGR0MyRzaXplX1QxLCBkdDMkc2l6ZV9UMiksCiAgdGhlbWUgPSB0bQopCnBsb3QocCkKCmxpYnJhcnkoZ3JpZCkKcCA8LSBlZGl0X3Bsb3QocCwKICAgICAgICAgICAgICAgcm93ID0gc2VxKGZyb209MSx0bz1ucm93KGR0MyksYnk9NyksCiAgICAgICAgICAgICAgIGdwID0gZ3Bhcihmb250ZmFjZSA9IGMoImJvbGQiLCJpdGFsaWMiKQogICAgICAgICAgICAgICAgICAgICAgICAgKSwgY29sID0gMSkKCnN0dWR5SW5kcyA8LSBzZXRkaWZmKDE6bnJvdyhkdDMpLHNlcShmcm9tPTEsdG89bnJvdyhkdDMpLGJ5PTcpKQpwYXJhbUluZHMgPC0gc2VxKGZyb209MSx0bz1ucm93KGR0KSxieT03KQoKcCA8LSBlZGl0X3Bsb3QocCwgcm93ID0gc3R1ZHlJbmRzLCB3aGljaCA9ICJiYWNrZ3JvdW5kIiwKICAgICAgICAgICAgICAgZ3AgPSBncGFyKGZpbGwgPSAid2hpdGUiKSkKcCA8LSBlZGl0X3Bsb3QocCwgcm93ID0gcGFyYW1JbmRzLCB3aGljaCA9ICJiYWNrZ3JvdW5kIiwKICAgICAgICAgICAgICAgZ3AgPSBncGFyKGZpbGwgPSAiZ3JleSIpKQoKYGBgCgpgYGB7cn0KcG5nKCJ+L0Rlc2t0b3AvUERfUmVjb3ZGb3Jlc3QucG5nIiwgdW5pdHM9ImluIiwgd2lkdGg9MTAsIGhlaWdodD0xOCwgcmVzPTMwMCkKcGxvdChwKQpkZXYub2ZmKCkKYGBgCgpgYGB7cn0KIyBnZ3NhdmUgZnVuY3Rpb24KZ2dwbG90Mjo6Z2dzYXZlKHBhc3RlMChzYXZldG8sIlBEX1JlY292Rm9yZXN0LnBuZyIpLAogICAgICAgICAgICAgICAgZHBpID0gMzAwLAogICAgICAgICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSAxNywgdW5pdHMgPSAiaW4iLCBwbG90PXApCgpnZ3Bsb3QyOjpnZ3NhdmUocGFzdGUwKHNhdmV0bywiUERfUmVjb3ZGb3Jlc3QudGlmZiIpLAogICAgICAgICAgICAgICAgZHBpID0gNjAwLAogICAgICAgICAgICAgICAgd2lkdGggPSA4LCBoZWlnaHQgPSAxNywgdW5pdHMgPSAiaW4iLCBwbG90PXApCmBgYA==